[C++]L-value와 R-value, R-value reference
L-value vs. R-value
인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다.
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!
L value
L value : 단일식을 넘어서 계속 지속되는 개체
- 메모리 위치를 참조.
- 주소가 있는 애들. 대개 식별자.
- const가 붙으면 수정할 수 없는 l-value가 된다.
R value
R value : L value가 아닌 나머지 (임시 값, 열거형, 람다, i++ 등)
- 표현식 종료 후 없어지는임시적인 값 리터럴 임시변수 임시객체.
- const 로 L value를 R value로 바꿀 수 있다.
L value Reference vs. R value Reference
L value Reference
- 원본을 넘겨준다.
- 원본 수정이 가능하다.
const L value Reference
- 원본을 넘겨준다.
- 원본 수정이 불가능하다. const로 원본 수정을 못하게 막아서 읽기만 하게 한다.
R value Reference
- 원본을 넘겨준다.
- 원본 수정이 가능하다.
- 이동! 함수가 이동되었다. 함수가 대체되어 원본은 더 이상 사용하지 않는다.
- R value Reference(오른값 참조)를 받는 '이동 대입 연산자 '와 함께 활용이 가능하다.
코드
더보기
#include <iostream> #include <vector> #include <list> #include <deque> #include <map> #include <set> #include <algorithm> using namespace std; // rvalue reference와 std::move class Pet { }; class Knight { public: Knight() { cout << "Knight()" << endl; } // 복사 생성자 Knight(const Knight& knight) { cout << "const Knight&" << endl; } // 이동 생성자 Knight(Knight&& knight) { } ~Knight() { if (_pet) delete _pet; } // 복사 대입 연산자 void operator=(const Knight& knight) { cout << "operator=(const Knight&)" << endl; // 깊은 복사 _hp = knight._hp; if (knight._pet) _pet = new Pet(*knight._pet); } // 이동 대입 연산자 void operator=(Knight&& knight) noexcept { cout << "operator=(Knight&&)" << endl; // 얕은 복사 _hp = knight._hp; _pet = knight._pet; knight._pet = nullptr; } public: int _hp = 100; Pet* _pet = nullptr; }; void TestKnight_Copy(Knight knight) { } void TestKnight_LValueRef(Knight& knight) { } //왼값 참조 void TestKnight_ConstLValueRef(const Knight& knight) { } void TestKnight_RValueRef(Knight&& knight) { } //오른값 참조, 이동 대상! int main() { // 왼값(lvalue) vs 오른값(rvalue) // - lvalue : 단일식을 넘어서 계속 지속되는 개체 // - rvalue : lvalue가 아닌 나머지 (임시 값, 열거형, 람다, i++ 등) //int a = 3; Knight k1; TestKnight_Copy(k1); TestKnight_LValueRef(k1); //TestKnight_LValueRef(knight()); TestKnight_ConstLValueRef(Knight()); TestKnight_RValueRef(Knight()); TestKnight_RValueRef(static_cast<Knight&&>(k1)); Knight k2; k2._pet = new Pet(); k2._hp = 1000; // 원본은 날려도 된다 << 는 Hint를 주는 쪽에 가깝다! Knight k3; //k3 = static_cast<Knight&&>(k2); k3 = std::move(k2); // 오른값 참조로 캐스팅 // std::move의 본래 이름 후보 중 하나가 rvalue_cast std::unique_ptr<Knight> uptr = std::make_unique<Knight>(); std::unique_ptr<Knight> uptr2 = std::move(uptr); return 0; }
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>
// rvalue reference와 std::move
class Pet
{
};
class Knight
{
public:
Knight()
{
cout << "Knight()" << endl;
}
// 복사 생성자
Knight(const Knight& knight)
{
cout << "const Knight&" << endl;
}
// 이동 생성자
Knight(Knight&& knight)
{
}
~Knight()
{
if (_pet)
delete _pet;
}
// 복사 대입 연산자
void operator=(const Knight& knight)
{
cout << "operator=(const Knight&)" << endl;
// 깊은 복사
_hp = knight._hp;
if (knight._pet)
_pet = new Pet(*knight._pet);
}
// 이동 대입 연산자
void operator=(Knight&& knight) noexcept
{
cout << "operator=(Knight&&)" << endl;
// 얕은 복사
_hp = knight._hp;
_pet = knight._pet;
knight._pet = nullptr;
}
public:
int _hp = 100;
Pet* _pet = nullptr;
};
void TestKnight_Copy(Knight knight) { }
void TestKnight_LValueRef(Knight& knight) { } //왼값 참조
void TestKnight_ConstLValueRef(const Knight& knight) { }
void TestKnight_RValueRef(Knight&& knight) { } //오른값 참조, 이동 대상!
int main()
{
// 왼값(lvalue) vs 오른값(rvalue)
// - lvalue : 단일식을 넘어서 계속 지속되는 개체
// - rvalue : lvalue가 아닌 나머지 (임시 값, 열거형, 람다, i++ 등)
//int a = 3;
Knight k1;
TestKnight_Copy(k1);
TestKnight_LValueRef(k1);
//TestKnight_LValueRef(knight());
TestKnight_ConstLValueRef(Knight());
TestKnight_RValueRef(Knight());
TestKnight_RValueRef(static_cast<Knight&&>(k1));
Knight k2;
k2._pet = new Pet();
k2._hp = 1000;
// 원본은 날려도 된다 << 는 Hint를 주는 쪽에 가깝다!
Knight k3;
//k3 = static_cast<Knight&&>(k2);
k3 = std::move(k2); // 오른값 참조로 캐스팅
// std::move의 본래 이름 후보 중 하나가 rvalue_cast
std::unique_ptr<Knight> uptr = std::make_unique<Knight>();
std::unique_ptr<Knight> uptr2 = std::move(uptr);
return 0;
}
|
cs |
'⭐ Programming > C++' 카테고리의 다른 글
callback 함수 (0) | 2023.09.18 |
---|---|
[C++] smart pointer (0) | 2022.04.26 |
[C++] 콜백 함수 (Callback function) (0) | 2022.04.17 |
[C++] 템플릿(Template) 2: 클래스 템플릿 (0) | 2022.04.17 |
[C++] 템플릿(Template) 1: 함수 템플릿 (0) | 2022.04.16 |
댓글
이 글 공유하기
다른 글
-
callback 함수
callback 함수
2023.09.18callback 함수는 다른 함수에게 인자로 전달되어 특정 이벤트 발생 시 호출되는 함수입니다. 어떤 함수(=혹은 메소드)를 실행하는 도중에 특정 이벤트가 발생하면, 이벤트 핸들러 함수인 콜백 함수가 자동으로 실행됩니다. 목차 callback 함수 callback 함수란? callback 함수는 다른 함수에게 인자로 전달되어 특정 이벤트 발생 시 호출되는 함수입니다. 어떤 함수(=혹은 메소드)를 실행하는 도중에 특정 이벤트가 발생하면, 이벤트 핸들러 함수인 콜백 함수가 자동으로 실행됩니다. callback 함수 실행 절차 1. 함수 포인터 전달 Callback 함수는 일반적으로 다른 함수에게 인자로 전달됩니다. 이때, Callback 함수의 메모리 주소를 가리키는 함수 포인터를 전달합니다. 2. 이벤트 … -
[C++] smart pointer
[C++] smart pointer
2022.04.26 -
[C++] 콜백 함수 (Callback function)
[C++] 콜백 함수 (Callback function)
2022.04.17콜백 함수 (Callback function) 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 콜백 함수 함수 포인터 + 함수 객체 + 템플릿 콜백 (Callback) : 다시 호출하다? 역으로 호출하다? 게임을 만들 때 이런 콜백의 개념이 자주 등장한다. ex) MoveTask 실습 등 어떤 상황이 일어나면 -> 이 기능을 호출해줘 ex) UI 스킬 버튼을 누르면 -> 스킬을 쓰는 함수를 호출 콜백 함수의 단점 함수 포인터는 상태를 저장할 수 없다. 함수 포인터로 콜백 함수를 만드는건 간단한 일이지만 상태를 저장할 수 없다는 단… -
[C++] 템플릿(Template) 2: 클래스 템플릿
[C++] 템플릿(Template) 2: 클래스 템플릿
2022.04.17클래스 템플릿 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 클래스 템플릿 #include using namespace std; class RandomBox{ public: int GetRandomData() { int idx = rand() % 10; return _data[idx]; } public: int _data[10]; }; int main(){ srand(static_cast(time(nullptr))); RandomBox rb1; for (int i = 0; i < 10; i++) { rb1._data[i] = i; } i…
댓글을 사용할 수 없습니다.