Home [C++] r-value 참조
Post
Cancel

[C++] r-value 참조

r-value 참조

r-value는 단순 대입 연산자의 오른쪽 항을 말하며

r-value로써 변수가 올 수도 있고 1, 5와 같은 리터널 상수가 올 수도 있습니다.

Ex. int a = 3; -> 3은 r-value

1에다가 5를 참조할 수 없듯이 변수가 아닌 대상(l-value)에 참조를 선언하는 건 허용되지 않았으나

C++11에 r-value에 대한 참조자가 나오면서 가능하게 되었습니다.

r-value 참조자의 문법은 아래와 같습니다.

1
2
// r-value 참조는 && 가 붙는다.
int&& a = 3;

언제 사용하는데?

아래 코드를 보면 묵시적 형변환으로 인해 int n이 Temp 클래스 임시 객체로 변환되는 것을 볼 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>

class Temp
{
private:
	int num = 0;
public:
	Temp() = default;
    // 파라미터가 1개인 생성자는 묵시적으로 형변환이 가능하다.
	Temp(int rhs) :num(rhs)
	{
		std::cout << "Enter: Temp(int rhs)" << std::endl;
	}
	int GetNum() const { return num; }
};

void TEST(Temp t)
{
	std::cout << "Enter: TEST(TEMP t)" << std::endl;
	std::cout <<"num: " << t.GetNum() << std::endl;
}

int main() 
{
	TEST(1 + 4);
}

// 출력 결과
Enter: Temp(int rhs)
Enter: TEST(TEMP t)
num: 5

위 코드에서 TEST(Temp t) 함수를 보면

우리가 보통 C++에서 클래스를 파라미터로 넘길 때 참조 형식으로 보내지만 값 형식으로 되어 있는 것을 볼 수 있습니다.

그러므로 코드를 아래와 같이 변경해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
// 클래스 생략

void TEST(Temp& t)
{
	std::cout << "Enter: TEST(TEMP& t)" << std::endl;
	std::cout <<"num: " << t.GetNum() << std::endl;
}

int main() 
{
	TEST(1 + 4); // compile error - 비const 참조에 대한 초기 값은 lvalue여야 합니다.
}

TEST() 함수의 파라미터를 Temp& t로 변경하니 컴파일 에러가 발생했습니다.

이때 const Temp& t로 변경하면 문제가 해결되지만 const가 되면 값 수정이 불가하게 되기 때문에 값 수정이 필요할 함수라면 문제 해결이 애매해지는데요.

이때 r-value 참조를 통해 해결할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void TEST(Temp& t)
{
	std::cout << "Enter: TEST(TEMP& t)" << std::endl;
	std::cout << "num: " << t.GetNum() << std::endl;
}

void TEST(Temp&& t)
{
	std::cout << "Enter: TEST(TEMP&& t)" << std::endl;
	std::cout <<"num: " << t.GetNum() << std::endl;
}

int main() 
{
	TEST(1 + 4);
}

// 출력 결과
Enter: Temp(int rhs)
Enter: TEST(TEMP&& t)
num: 5

내용을 정리하면 아래와 같습니다.

  • 1+4은 r-value 연산에 대한 임시 객체이기 때문에 참조 형식 l-value에 할당할 수 없다
1
int& a = 4; // compile error - 비const 참조에 대한 초기 값은 lvalue여야 합니다.
  • 그러므로 r-value 연산에 대한 임시 객체인 (1+4)를 받기 위해선 r-value 참조를 사용해야 한다.
1
int&& a = 4; // it's ok.

함수의 모호성

위와 같이 r-value를 사용하기 위해선 아래와 같은 함수의 모호성에 대해 조심해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void TEST(Temp t)
{
	std::cout << "Enter: TEST(TEMP t)" << std::endl;
	std::cout << "num: " << t.GetNum() << std::endl;
}

void TEST(Temp&& t)
{
	std::cout << "Enter: TEST(TEMP&& t)" << std::endl;
	std::cout <<"num: " << t.GetNum() << std::endl;
}

int main() 
{
	// Compile Error! - 오버로드된 함수 "TEST"의 인스턴스 중 두 개 이상이 인수 목록과 일치합니다.
	TEST(1 + 4); 
}
This post is licensed under CC BY 4.0 by the author.

[C++] default 와 delete 예약어

[Unity] 구면 좌표계로 3인칭 카메라 움직임 구현하기