rule of three/five/zero란
멤버 변수로 raw pointer(예를 들면 char * mPtr)를 활용해 리소스를 관리하게되면
개발자가 직접
먼저 객체를 만들어보면
#include <iostream>
#include <string>
using namespace std;
class Cat {
public:
Cat(string name, int age):mName{(move(name))}, mAge(age){};
void print() {
cout << mName << " " << mAge << endl;
}
private:
string mName;
int mAge;
char *
}
int main() {
Cat kitty{"kitty", 1};
Cat nabi;
return 0;
}
를 컴파일 할 경우 nabi객체를 만드는데 컴파일 에러가 생기는데
생성자에서 Cat(string name, int age)처럼 2개의 인수를 받는 생성자를 선언했기 때문에 인수를 받지않는 생성자를 disabled시켰기 때문이다.
따라서 Cat()=default;라고 알려주면 컴파일러가 자동적으로 만들어주는 default constructor를 사용해서 구현이 된다.
#include <iostream>
#include <string>
using namespace std;
class Cat {
public:
Cat()=default;
Cat(string name, int age):mName{(move(name))}, mAge(age){} {
cout << "constructor" << endl;
}
void print() {
cout << mName << " " << mAge << endl;
}
~Cat() {
cout << "destructor" << endl;
}
private:
string mName;
int mAge;
char * mPtr
}
int main() {
Cat kitty{"kitty", 1};
Cat nabi;
return 0;
}
char * mPtr처럼 포인터를 이용해 리소스를 관리한다면
~Cat() destructor부분에서 delete mPtr;를 통해 해제해주어야한다.
copy constructor는 기존의 object를 똑같이 copy해서 새로운 object를 만드는 메서드이다.
#include <iostream>
#include <string>
using namespace std;
class Cat {
public:
Cat()=default;
Cat(string name, int age):mName{(move(name))}, mAge(age){} {
cout << "constructor" << endl;
}
Cat(const Cat& other):mName{other.mName}, mAge{other.mAge} {
cout << "copy constructor" << endl;
}
void print() {
cout << mName << " " << mAge << endl;
}
~Cat() {
cout << "destructor" << endl;
}
private:
string mName;
int mAge;
char * mPtr
}
int main() {
Cat kitty{"kitty", 1};
Cat kitty2{kitty};
Cat kitty3 = kitty;
return 0;
}
Cat kitty3 = kitty;에서 "="때문에 assignment가 개입될 거라 생각할 수 있지만
새로운 object가 만들어지는 과정이라 copy constructor가 호출된다.

코드를 실행해보면 먼저 kitty constructor가 생긴 뒤 copy constructor들이 실행되는 것을 알 수 있다.
move constructor
기존 object를 복사하는 copy constructor와 달리
move constructor는 기존 object의 ownership을 뺏어오는 방식이다
R value reference를 만들어서
Cat(Cat &&other):mName{std::move(other.mName)}, mAge{other.mAge}