copy assignment
object1과 object2가 있고
object2를 object1에 assignment한다고 하면
object2의 내용이 object1에 전부 복사된다.

Cat & operator=(const Cat& other) {
mName = other.mName;
mAge = other.mAge;
cout << "copy assignment << endl;
return *this
}
copy assignment의 return 타입은 reference이다.
그러므로 이 object의 주소가 가리키는 것을 리턴해주면 된다(return *this)
int main() {
Cat kitty{"kitty", 1};
Cat nabi{"nabi", 2};
kitty = nabi;
kitty.print();
}
를 출력해보면 nabi object의 정보가 모두 kitty에 복사되어
nabi 2가 출력된다.
2개의 object가 있을 때 object2가 R value라면
object2의 내용이 copy되는 것이 아니라 move된다
Cat & operator=(const Cat&& other) {
mName = std::move(other.mName);
mAge = other.mAge;
cout << "move assignment << endl;
return *this
}
string object인 other.mName은 R value로 바꾸고 ownership을 뺏어올 수 있다.
int 타입인 mAge는 복사를 해주었다.
move assignment를 call해주기 위해
int main() {
Cat kitty{"kitty", 1};
Cat nabi{"nabi", 2};
kitty = std::move(nabi);
kitty.print();
nabi.print();
}
kitty = std::move(nabi);를 사용하였다

출력해보면 kitty object에게 string의 ownership을 빼앗겨 nabi없이 2만 출력되는 것을 볼 수 있다.
self assignment
int main() {
Cat kitty{"kitty", 1};
Cat nabi{"nabi", 2};
kitty = kitty;
kitty = std::move(kitty);
}
이 상태로 빌드하면 문제없이 빌드가 된다
그러나 char * mPtr처럼 char pointer를 이용해 리소스 관리를 해주었다면
예상치 못한 일들이 생길수 있다
이를 방지하기 위해 두 개가 같은 object라면 자기자신을 return해주는 코드를 넣는다
Cat & operator = (Cat && other) {
if (&other == this) {
return * this;
}
...
...
}
kitty = nabi; // copy assignment
kitty = std::move(nabi); // move assignment
가 일어났을때를 그림으로 보면

copy assignment는 kitty의 내용이 nabi의 내용으로 copy되는 것을 알 수 있고

move assignment는 nabi에서 가리키던 것이 kitty가 가리키도록 ownership이 변경된다는 것을 알 수 있다.
destructor, move assignment, move constructor는 exception이 던져지지 않기 때문에 noexcept를 붙여주는 것이 중요하다.

앞에서 말했듯 char * mPtr처럼 포인터를 이용해 리소스를 관리하지 않는다면
Cat(), ~Cat(), Cat(Cat& other)등 이렇게 직접 만들 필요는 없다.

int main() {
Cat kitty{"kitty", 1};
Cat nabi{"nabi", 2};
kitty = kitty;
kitty = std::move(kitty);
}
이렇게 포인터를 이용하지 않는 상태에서 copy, move constructor를 정의하지않고 빌드해도
컴파일러가 알아서 만들어주기 때문에 괜찮다.
따라서 생산성 높은 c++개발을 하고싶다면 포인터를 이용한 리소스관리는 피해주는 것이 좋다.
constructor, copy constructor, copy assignment를 막는 방법은
Cat() = delete;
Cat(const Cat& other) = delete;
Cat& operator = (const Cat& other) = delete;
처럼 = delete를 붙여주면 된다.
C++ 11이전에는

이렇게 private안에 넣어두는데 이는 = delete를 붙이는 것과 똑같이 동작한다.
static method만 가지고 있는 class의 경우 object를 만들 필요가 없다.
그럴 때는 Cat() = delete;를 이용해 constructor자체를 막는 것도 좋은 방법이다.
singleton pattern의 경우 하나만 있어야하므로 copy constructor, copy assignment자체가 존재하면 안되므로 막는 것이 좋다.