C++11에서 도입된 중요한 이동 의미론(Move Semantics)을 한 번 정리해야겠다 싶어서 게시하는 글이다
불필요한 복사 대신 한 객체에서 다른 객체로 리소스를 효율적으로 전달하는 것을 의미한다
#include "bits/stdc++.h"
using namespace std;
class Person
{
public:
Person(string name, int age) : name(name), age(age)
{
cout << "생성자 호출!" << endl;
}
// 복사 생성자
Person(const Person& p) : name(p.name), age(p.age)
{
cout << "복사 생성자 호출!" << endl;
}
// 이동 생성자
Person(Person&& p)
{
name = move(p.name);
age = p.age;
cout << "이동 생성자 호출!" << endl;
}
string name;
int age;
};
int main()
{
Person p1("CHO", 26);
cout << "-------------------" << endl;
Person p2(p1);
cout << "-------------------" << endl;
Person p3(move(p1));
cout << "-------------------" << endl;
// p1을 Move해 p3를 생성해서 p1.name은 빈 문자열이 되었음
cout << p1.name << endl;
return 0;
}

p1은 기본 생성자로 생성했고 p2는 p1이라는 왼값을 매개변수로 전달해 복사 생성자가 호출되고 p3는 move 함수를 통해 p1을 오른값으로 캐스팅해 이동 생성자를 호출했다
그리고 move가 적용된 p1은 기존에 name값이 p3로 이동했기에 출력해보면 빈 문자열이 출력된다
왼값 참조와 오른값 참조를 구분해서 함수를 호출해보자
void Print(Person p)
{
cout << "Lvalue Ref" << p.name << " " << p.age << endl;
}
void Print(Person&& p)
{
cout << "Rvalue Ref" << p.name << " " << p.age << endl;
}
int main()
{
...
Print(p1);
Print(move(p2)); // 컴파일 에러
}
첫 번째 호출 식에서는 첫 번째 Print 함수가 호출이 되는 반면 두 번째 호출 식은 컴파일 에러가 난다

첫 번째 호출은 누가봐도 왼값이 분명하기에 첫 번째 Print가 호출이 되는 반면 두 번째는 p2에 move를 취해 오른값으로 캐스팅했긴 했는데 Print 함수로 전달될 때에는 왼값으로 전달되어 어떤 함수를 선택해야 될 지 몰라 생기는 에러같다
컴파일되게 하려면 Print(Person p)를 바꿔야 하는데 이 함수는 왼값과 오른값 모두 받을 수 있기 때문임
정답부터 보면 Print(const Person& p)로 바꿔주어야 컴파일이 되는데

Print(Person& p)는 왜 안될까? 이것도 왼값, 오른값 둘 다 받을 수 있기 때문이다(설명이 좀 어렵네 ㅠㅠ)
쉽게 말해 복사와 이동을 잘 구분해야 할 것 같다,, 다른 블로그에 정리 잘 되어 있으니까 그거 보는게 더 나을 것 같아요