프로그래밍/C/C++

C++ rvalue reference 우측값 참조 속성

nanze 2022. 1. 7. 10:30
반응형

이전 정리글

2022.01.06 - [프로그래밍/C/C++] - C++ rvalue reference (우측값 참조) move semantics

 

C++ rvalue reference (우측값 참조) move semantics

이전 정리글은 2022.01.05 - [프로그래밍/C/C++] - C++ Lvalue (좌측값) Rvalue (우측값) Rvalue reference (우측값 참조자) C++ Lvalue (좌측값) Rvalue (우측값) Rvalue reference (우측값 참조자) c++ lvalue..

nanze.tistory.com

 

우측값(rvalue)은 함수의 인자로 넘어갈 때 우측값 참조자(rvalue reference) 뿐만이 아니라 const 타입의 좌측값 참조자(lvalue reference)로도 넘겨질 수 있다. 같은 함수가 존재할 경우 우측값 참조자의 우선순위가 더 높다.

이번 정리는 우측값 참조의 속성에 대해서 알아보자. 우선 예제 코드를 보자.

#include <iostream>
#include <vector>
using namespace std;

class clsObject
{
public:
	clsObject(size_t sz) {
		mSize = sz;
		mData = new uint8_t[sz];
	}
	~clsObject() {
		if (mData != nullptr) {
			delete[] mData;
		}
	}
	
private:
	size_t mSize;
	uint8_t* mData;
};

void func(const clsObject& cls)
{
    wcout << "const clsObject& cls" << endl;
}

void func(clsObject&& cls)
{
    wcout << "clsObject&& cls" << endl;
}

int main()
{
    clsObject obj(10);
    func(obj);
    func(clsObject(12));
    return 0;
}

위 코드를 보면 동일한 func 이 존재하며 위에 함수는 좌측값 참조를 아래 함수는 우측값 참조를 인자로 사용하고 있다. main 에서 func 함수 호출 시 obj 를 인자로 넘긴 func 는 lvalue 가 전달되었기에 위에 함수가 호출되며 두번째 func() 는 clsObject(12)  rvalue 이기에 우측값 참조를 인자로 사용하는 func 이 호출된다. 여기서 유의해야 할 점은 인자가 rvalue 일 경우 첫번째, 두번째 func 모두 호출될 수 있다. 왜냐하면 첫번째의 좌측값 참조 앞에 const 가 붙었으므로 rvalue 도 받을 수 있다. 하지만 && 표현식의 우선 순위가 높기 때문에 후자의 func() 가 호출된다.  

좌측값(lvalue)은 우측값 참조자(rvalue reference) 타입으로 캐스팅될 수 있다. 

다음 예제 코드를 보자.

#include <iostream>
#include <vector>
using namespace std;

class clsObject
{
public:
	clsObject(size_t sz) {
		mSize = sz;
		mData = new uint8_t[sz];
	}
	~clsObject() {
		if (mData != nullptr) {
			delete[] mData;
		}
	}
	
private:
	size_t mSize;
	uint8_t* mData;
};

void func(const clsObject& cls)
{
    wcout << "const clsObject& cls" << endl;
}

void func(clsObject&& cls)
{
    wcout << "clsObject&& cls" << endl;
}

int main()
{
    clsObject obj(10);
    func(obj);
    func(static_cast<clsObject&&>(obj));
    func(std::move(obj));
    return 0;
}

위의 코드를 보면 알 수 있는 것은 좌측값은 우측값 참조로 type casting 될 수 있다는 것을 보여준다. std::move 함수는 강제로 우측값 참조로 type casting 해주는 역할을 하는 함수이다. 

 

우측값 참조자(rvalue reference) 타입의 함수 인자 변수 자체는 함수 내부에서 좌측값(lvalue)이다.

세번째 코드를 보도록 하자.

#include <iostream>
#include <vector>
using namespace std;

class clsObject
{
public:
	clsObject(size_t sz) {
		mSize = sz;
		mData = new uint8_t[sz];
	}
	~clsObject() {
		if (mData != nullptr) {
			delete[] mData;
		}
	}
	
private:
	size_t mSize;
	uint8_t* mData;
};

void func(clsObject&& cls)
{
    wcout << "clsObject&& cls" << endl;
}

clsObject&& func2(clsObject&& cls)
{
    return std::move(cls);
}

int main()
{
    clsObject obj(10);
    func(func2(std::move(obj)));
    return 0;
}

위 코드에서 보여주는 것은 무엇인가? func2 함수는 우측값 참조(rvalue reference)를 반환하고 있으며 인자로 또한 우측값 참조(rvalue reference)를 받고 있다. 그런데 함수 내부에서 들어온 인자에 대해서 std::move 를 해주고 있다. 왜인가? 그렇다. 들어온 인자의 타입 자체는 우측값 참조(rvalue reference)이나 넘어온 인자 변수 cls 자체는 좌측값(lvalue) 이기 때문이다.

 

다음 정리글은

2022.01.07 - [프로그래밍/C/C++] - C++ Universal reference & Reference Collapsing Rules

 

C++ Universal reference & Reference Collapsing Rules

이전 정리글은 2022.01.07 - [프로그래밍/C/C++] - C++ rvalue reference 우측값 참조 속성 C++ rvalue reference 우측값 참조 속성 이전 정리글 2022.01.06 - [프로그래밍/C/C++] - C++ rvalue reference (우측값..

nanze.tistory.com

 

 

 

 

 

반응형