C++ 11에서 Rvalue reference를 공부하다보니 처음보는 개념들이 너무 많이 쏟아져 나온다. 그중 하나가 std::move이다.
기능은 쉽게 이야기해서 lvalue를 rvalue로 전환해주는 것이 전부이다. 다만 B = std::move(A)를 한다면, A는 아무런 값도 갖지 않은 객체가 된다는 것을 인지해야한다. 이름이 move라고 해서 값을 옮겨준다거나 그렇게 하진 않는다. std::move는 주로 move 생성자에 많이 쓰인다.
아래 코드를 보면 왜 move 생성자에서 자주 쓰이는지 알 수 있다. (코드 출처 : https://openmynotepad.tistory.com/10)
class Item {
public:
Item(const int _n) : m_nx(_n) { cout << "일반 생성자 호출" << endl; }
Item(const Item& rhs) : m_nx(rhs.m_nx) { cout << "복사 생성자 호출" << endl; }
Item(const Item&& rhs) : m_nx(std::move(rhs.m_nx)) { cout << "이동 생성자 호출" << endl; }
~Item() { cout << "소멸자 호출" << endl; }
private:
int m_nx;
};
move 생성자에서 std::move를 사용한 것을 확인할 수 있다. rhs의 m_nx멤버를 lvalue에서 rvalue로 전환해주고 있는데
사실 이전의 rvalue reference글에서의 move 생성자도 이렇게 써도 똑같다.
// Move 생성자
MemoryBlock(MemoryBlock&& other) : _data(NULL), _length(0)
{
std::cout << "Move Constructor Length : " << other._length << std::endl;
*this = std::move(other);
/* 원래는 위의 한줄을 아래와 같이 4줄에 걸쳐서 썼음 */
/*
_data = other._data;
_length = other._length;
other._data = NULL;
other._length = 0;
*/
}
std::move에 대해 더 이해가 잘되는 예시 코드를 써주신 분이 있어서 가져와봤다
void func(const Widget& rhs)
{
cout << "const Widget&" << endl;
}
void func(Widget&& rhs)
{
cout << "Widget&& " << endl;
}
int main()
{
Widget A;
func(std::move(A)); // 이제 func(Widget&& rhs) 버전이 호출됨
func(static_cast<Widget&&>(A)); // std::move 와 같음
}
더 이상 lvalue로써의 참조가 필요 없을 때 std::move(A)를 사용함으로써 소유권을 이전할 수 있다. 결과적으로 Move Constructor가 호출될 것 이다. 이는 static_cast로 Widget&& 타입으로 캐스팅한 것과 같은 결과를 가져온다.
Reference:
https://openmynotepad.tistory.com/10
https://openmynotepad.tistory.com/21?category=853099
'공부 > C || C++' 카테고리의 다른 글
C++ vector::push_back vs vector::emplace_back (0) | 2022.09.18 |
---|---|
STL Container (시퀀스 컨테이너, 연관 컨테이너, 컨테이너 어댑터) (0) | 2022.09.17 |
C++ 11 RVO(Return Value Optimization) (0) | 2022.08.29 |
const 멤버 함수의 리턴 타입을 레퍼런스로 할 수 없는 이유/ const 멤버함수 내부에서 const가 아닌 멤버 함수를 호출할 수 없다 (0) | 2021.11.12 |
C++ const가 붙는 위치에 따른 의미변화 (0) | 2021.09.01 |