위의 표현식에서 a는 메모리상의 변수, 즉 a는 주소값을 &연산자로 알 수 있다.
이렇게 주소값을 취할 수 있는 값을 lValue라고 한다.
그리고 lValue는 표현식의 왼쪽과 오른쪽 모두 올수 있다.
반면 3은 그 주소를 얻을 수 있는 값이 아니다.
3은 위의 표현식을 연산할 때 잠깐 존재한 후 연산이 끝나고 나면 사라지는 값이다. 즉 실체가 없는 값이다.
이렇게 실체가 없는 값을 rValue라고 한다.
rValue는 항상 오른쪽에만 존재 해야 한다.
lvalue : 실체가 있는 값
xvalue : 문장이 끝나면 곧 사라질 값
prvalue : 상수의 값, 상수를 만들어 내는 수식의 값, 함수가 반환하는 값
#ifndef _VECF_H_
#define _VECF_H_
#include <cstring>
#include <iostream>
using namespace std;
class VecF
{
int n;
float* arr;
public:
// 생성자
VecF(int d, const float* a = nullptr) : n{ d } {
arr = new float[d];
if (a) {
memcpy(arr, a, sizeof(float)* n);
}
}
// 복사생성자
VecF(const VecF& ref) : n{ref.n} {
arr = new float[n];
memccpy(arr, ref.arr, sizeof(float) * n);
}
// 소멸자
~VecF() {
delete[] arr;
}
// 두 벡터를 더해 반환
VecF add(const VecF& fv) const {
VecF tmp(n);
for (int i = 0; i < n; i++) {
tmp.arr[i] = arr[i] + fv.arr[i];
}
return tmp;
}
// 출력
void print() const {
cout << "[ ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "]" << endl;
}
};
#endif // !_VECF_H_
VecF v1(3), v2(3);
VecF& vLRef = v1; // lvalue 참조
int& a = 10; // 오류
const int& b = 20; // 상수 lvalue로 rvalue 참조
int&& c = 30; // rvalue 참조
VecF&& vRRef1 = v1.add(v2);
VecF&& vRRef2 = v2; // 오류 rvalue참조로 lvalue를 참조할수 없음
VecF클래스의 add함수 호출시 반환값에 대한 복사생성자를 호출하는 경우 비효율적인 복사가 이루어지므로 이동생성자를 이용하여 이동시킨다.
class ClassName {
...
public:
ClassName(ClassName&& obj) {
...
}
}
VecF(VecF&& obj) : n{obj.n}, arr{obj.arr} {
obj.arr = nullptr;
obj.n = 0;
}