[Modern C++][C++11] Rvalue Reference and move semantics
다음 링크를 통해 공부하자.
모두의 코드 사이트가 그나마 가장 보기 쉬운 것 같다.
www.learncpp.com/cpp-tutorial/rvalue-references/
www.learncpp.com/cpp-tutorial/move-constructors-and-move-assignment/
blog.naver.com/devmachine/178065606 ([C++11] Rvalue Reference #2 - Move Semantics )
[C++11] Rvalue Reference 강좌 모음
C++11 Rvalue Reference 강좌 모음 제 블로그에 포스팅했던 Rvalue Reference 강좌의 링크를 보기 쉽...
blog.naver.com
씹어먹는 C++ - <12 - 2. Move 문법 (std::move semantics) 과 완벽한 전달 (perfect forwarding)>
modoocode.com
(좀 옛날 글인데, modoocode.com/189)
문자열과 그 길이 정보를 담고 있는 MyString 클래스 (= std::string) 예시를 보자 (위 모두의코드 링크)
복사 생성자 vs 이동 생성자
MyString::MyString(const MyString &str)
다른 Mystring str(lvalue) 받아서, 그 길이만큼 메모리 할당 후 character 일일히 똑같이 붙여넣기
MyString::MyString(MyString &&str)
똑같이 다른 Mystring str(rvalue) 받되,
str의 포인터, 사이즈, 메모리 할당량 정보 등을 assignment =로 그대로 옮기기만 함 (복사X)
assignment = 를 통한 복사 vs 이동
위와 비슷.
복사는 실제로 할당한 메모리에 정보 똑같이 붙여넣기 하고,
이동은 pointer나 기타 값들만 =로 옮겨줌
즉, 이동이 복사보다 훨씬 computationally efficient함.
* move는 인자로 받은 lvalue를 rvalue로 바꿔주는 역할. 이름과 달리 뭔가를 move하지 않음
우측값 = move(좌측값)
Q. Rvalue reference는 왜 필요한거야? 어디 쓰이는건데?
얄팍하게 공부해본 바로는, '복사/대입 연산자 구현할때 불필요한 과정을 줄이려고 + parameter forwarding 해주는 wrapper 만들 때 다른 타입때문에 생기는 컴파일 오류를 잡아내려고' 정도인데, 아직 이게 쓸만한건지 잘 모르겠다
[16July21] 복사 연산자보다 훨씬 효율적인 '이동' 연산을 구현하고싶은데, 기존의 lvalue reference & 만 가지고는 input parameter가 rvalue인지 알 수 없어서 새롭게 도입함.
rvalue referece -> move semantic + parameter forwarding
* const T& 로 우측값 레퍼런스 받을 수 있다
그 이유는 const 레퍼런스 이기 때문에 임시로 존재하는 객체의 값을 참조만 할 뿐 이를 변경할 수 없기 때문입니다.
(가끔 코드짜면서 레퍼런스 앞에 const 해줘야 하는 에러 만나는데 이것 때문인 듯?)
R-value 가지고 놀아봄.
Q. R-value reference로 value 바꿀 수 있나? (이러라고 있는 기능이 아니지만, 'reference'를 통해 실제 값이 바뀌는지 궁금하다
int&& a = 5; // type : int&& cout << a << "\n"; a = 3; cout << a; /* Output 5 3 */
근데 이건 그냥 a 메모리 주소에 있는 값을 바꾼 것 아닌가?
좀 더 해보자.
// 1차원 배열 vector<int> v(10); iota(v.begin(), v.end(), 1); cout << v << "\n"; // 벡터 출력 함수 따로 정의 int& refer = v[1]; // type : int& // int&& refer = v[1]; // Syntax 에러 auto&& refer = v[1]; // type : int& refer = 100; cout << v << "\n"; /* Output [ 1 2 3 4 5 6 7 8 9 10 ] [ 1 100 3 4 5 6 7 8 9 10 ] */
// 2차원 배열 vector<vector<int>> v(5, vector<int>(5, 2)); print::vec2d_print(v); cout << "\n"; // 2-D 벡터 출력 함수 따로 정의 int& refer = v[1][1]; // int & // int&& refer = v[1][1]; // Syntax error auto&& refer = v[1][1]; // int & refer = 0; print::vec2d_print(v); /* Output 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 */
일반적인 값은 lvalue reference(&)로만 참조할 수 있다. Rvalue reference(&&)는 syntax 오류가 난다.
또 신기한 점은, auto&&를 쓰면 자동으로 lvalue reference가 된다는 점이다.
그런데, 한 가지 신기한 점을 발견했다. 바로 vector<bool>이다.
bool&은 아예 안되고, bool&& 과 auto&&가 되는데,
신기하게도 bool&&로 참조한 것은 값을 변경해도 실제 벡터 원소가 변경되지 않는다.
// 2차원 배열; vector<bool> vector<vector<bool>> v(5, vector<bool>(5, false)); print::vec2d_print(v); cout << "\n"; // 2-D 벡터 출력 함수 따로 정의 //bool& refer = v[1][1]; // 비const 참조에 대한 초기 값은 lvalue여야 합니다. bool&& refer = v[1][1]; // bool&&, 그러나 v[1][1]의 값을 바꾸지 못함 auto&& refer = v[1][1]; // std::_Vb_reference<std::_Wrap_alloc<std::allocator<unsigned int>>> && refer = true; print::vec2d_print(v); /* Output (auto&&에 대해서만) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */
찾아보니까 vector<bool>은 조금 다르다고 하다.
stackoverflow.com/questions/8399417/why-vectorboolreference-doesnt-return-reference-to-bool
'<언어> > [C++]' 카테고리의 다른 글
[Modern C++][C++11] nullptr (0) | 2021.05.11 |
---|---|
[C++] Class 공부 & instantiation (+ Struct) (0) | 2021.03.24 |
[C++] Operator overloading (연산자 오버로딩) (0) | 2021.02.08 |
[C++] Type Conversion 정리 (0) | 2020.12.07 |
[C++] sorting (0) | 2020.12.06 |