이동생성자(Move Constructor)

lValue 와 rValue

int a = 3;

위의 표현식에서 a는 메모리상의 변수, 즉 a는 주소값을 &연산자로 알 수 있다. 이렇게 주소값을 취할 수 있는 값을 lValue라고 한다. 그리고 lValue는 표현식의 왼쪽과 오른쪽 모두 올수 있다.

반면 3은 그 주소를 얻을 수 있는 값이 아니다. 3은 위의 표현식을 연산할 때 잠깐 존재한 후 연산이 끝나고 나면 사라지는 값이다. 즉 실체가 없는 값이다. 이렇게 실체가 없는 값을 rValue라고 한다. rValue는 항상 오른쪽에만 존재 해야 한다.

lvalue : 실체가 있는 값 xvalue : 문장이 끝나면 곧 사라질 값 prvalue : 상수의 값, 상수를 만들어 내는 수식의 값, 함수가 반환하는 값

VecF 클래스

VecF.h
#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_

r-Value 참조

&& 기호로 선

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를 참조할수 없음

이동생성자(Move Constructor)

VecF클래스의 add함수 호출시 반환값에 대한 복사생성자를 호출하는 경우 비효율적인 복사가 이루어지므로 이동생성자를 이용하여 이동시킨다.

이동생상자의 선언형식
class ClassName {
    ...
public:
    ClassName(ClassName&& obj) {
        ... 
    }
}

VecF 클래스에 이동생성자 구현

VecF(VecF&& obj) : n{obj.n}, arr{obj.arr} {
    obj.arr = nullptr;
    obj.n = 0;
}

Last updated