임시적이지 않은것...
이름이 있는 것, 변수 있는 것 ..
단일 식을 넘어 지속되는 개체
결국 지금까지 봐온 많은 것들
Ex)
int number = 10;// number 는 lvalue
const int NAME_MAX = 20;// NAME_MAX 는 lvalue
int* numberPtr = &number;// numberPtr 는 lvalue
std::map<std::string, float> scoreMap;
scoreMap["Lulu"] = 60.f;// scoreMap 는 lvalue
struct Person
{
std::string Name;
int Age;
}
int main()
{
Person person;
person.Name = "Lulu";// person.Name 는 lvalue
const char* name = "Gragas";// name는 lvalue
}
- 뭔가 저장 할 수 있는 식을 lvalue라고 한다.
rvalue
lvalue가 아닌 개체
"사용되는 단일 식을 넘어 지속되지 않는 일시적인 값", "컨트롤 할 수 없는 값"
Ex)
// 10은 rvalue, 10이란 것에 값을 쓸 수 있음?? 없다... 임시적이다 이 구문 넘어가면 참조 못함.
int number = 10;
10 = number;// error, 값을 쓸 수 없다.
(number + 1) = 10;// error, 값이 rvalue이기 때문에.
int anotherNumber = 20;
int result = number + anotherNumber;// number + anotherNumber 는 rvalue
&number = 20;// error, &number는 rvalue이기 때문에.
int number1 = 10;
int number2 = 20;
if(number1 < number2)// number1 < number2 도 rvalue
{
}
과거 C++의 문제점
vector<float> Math::ConvertToPercentage(const std::vector<float>& scores)
{
std::vector<float> percentages;
for(vector<float>::const_iterator iter = scores.begin(); iter != scores.end(); ++iter)
{
percentages 변환
}
return percentages;// 1번째 복사, percentages를 임시개체로 복사함.
}
int main()
{
vector<float> scores;
scores = ConvertToPercentage(scores);// 2번째 복사, 임시개체를 scores 로 복사
}
복사를 어떻게 막을까??
rvalue 참조, (&&)
Ex)
float CalculateAverage()
{
float average;
return average;
}
int main()
{
int number = 10;
in&& rNumber = number;// error, number는 lvalue 이다.
int&& rNumber1 = 10;// Ok, 10은 rvalue 이다.
float&& rAverage = CalculateAverage();// ok, CalculateAverage 는 rvalue
}
class MyString
{
public:
MyString(MyString&& other);// 복사 생성자와 굉장히 비슷, const를 뺏다 왜 ?? 원본을 털어올 거니까...
MyString(const MyString& other);
MyString(const char* str);
private:
char* mString;
int mSize;
}
MyString::MyString(MyString&& other)
: mString(other.mString)// 얕은 복사를 한다.
, mSize(other.mSize)
{
other.mString = nullptr;// 원본을 다 턴다.
other.mSize = 0;
}
MyString studentName("Lulu");
MyString copiedName(std::Move(studentName));
// studnetName 에는 아무것도 안 남아 있을 것이다 추측할 수 있다.
class MyString
{
public:
MyString& operator=(MyString&& other);// 이동복사생성자와 비슷
private:
char* mString;
int mSize;
}
MyString MyString::operator=(MyString&& other)
: mString(other.mString) // 얕은 복사를 한다.
, mSize(other.mSize)
{
if(this != &other) // 본인이 본인한테 대입하지 않는 경우에만 동작
{
// 원래 가지고 있던 메모리 정리.
// 이동 생성자는 이거 할 필요가 없음, 생성자일 때는 처음 생성하는 거니까...
// 대입은 기존의 메모리를 가지고 있을 수 있음
delete[] mString;
// 얕은 복사.
mString = other.mString;
mSize = other.mSize;
// 원본 털기
other.mString = nullptr;
other.mSize = 0;
}
}
MyString studentName("Lulu");
MyString copiedName("Teemo");// studnetName 에는 아무것도 안 남아 있을 것이다 추측할 수 있다.
studentName = std::move(copiedName);
int main()
{
std::vector<float> scores;
scores = Math::ConvertToPercentage(scores);
// scores가 복사가 아닌 임시 개체를 참조 하게 된다.
}
임시 개체 -> [10][20][30]...(scores가 가지고 있던 메모리)
scores -> [1%][2%][3%] ...(임시개체가 가지고 있던 메모리)
std::swap()이라는 함수가 있음... 이를 이용하는가 보다.