갱신되는 객체가 원본? 기준? 이 되는 객체를 대입할 경우 copy 형식으로
진행이 되는 함수.
복사 대입생성자가 호출되기 위해서는 초기화된 2개의 객체가 필요하다.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Cat
{
private :
string mName;
int mAge;
public :
Cat() = default;
Cat(string name , int age ) : mName{ move(name) }, mAge{age}
{
cout << mName << "constructor" << endl;
}
~Cat()
{
cout << mName << "destructor" << endl;
}
//복사 생성자.
Cat(const Cat& other) : mName{ other.mName }, mAge{ other.mAge }
{
cout << mName << "Copy 생성자 " << endl;
}
//이동 생성자.
Cat(Cat && other) :mName{ move(other.mName) }, mAge{ other.mAge }
{
cout << mName << "이동 생성자 " << endl;
}
Cat& operator=(const Cat & other)
{
mName = other.mName;
mAge = other.mAge;
cout << mName << " copy assignment " << endl;
return *this;
}
void print()
{
cout << mName << " " << mAge << endl;
}
};
int main()
{
Cat kitty{"키티", 1};
Cat navi{ "나비", 2 };
kitty = navi;
kitty.print();
return 0;
}
선언과 동시에 대입하게 되면 어떻게 될까?
-> 앞의 강의에서 공부한 것처럼, 컴파일러가 센스있게 선언과 동시에 초기화하면 복사생성자를 호출시킨다.
복사 생성자 일 때의 주소 비교
-> 깊은 복사가 진행되었다.
복사 대입연산자 일 때의 주소 비교
-> 깊은 복사가 진행되었다.
객체의 value를 복사하는 의미는 동일하다.
복사생성자는 갱신되는 객체의 선언과 동시에 원본을 받아 초기화할 때 호출된다.
복사 대입 생성자는 2개의 객체가 모두 초기화가 이루어진 후에 대입을 할
경우에 호출된다.
: 갱신 받을 객체가 원본, 기준이 되는 객체를 RValue 형식으로 받으면
move 형식으로 진행이 되는 함수
-> navi의 mName이 kitty에게 빼앗껴서 navi의 소멸자(생성을 가장 늦게 했으니 소멸자는 가장 먼저 호출됨.)에서 mName값이 나오지 않는 것을 확인할 수 있따.
-> 원본이 다른 공간으로 이동된다.
: 자기 자신을 대입하거나, move 하면 어떻게 될까?
-> 일반적인 데이터 타입은 이상이 없다.
: 소멸자, 이동생성자, 이동 대입 생성자는 noexcept를 사용해서 예외처리 되는 것을 방지하자.
-> 3개의 함수는 새로운 리소스? 를 요청하지 않으므로 exception이 발생할 수 없다. noexcept를 붙이면 컴파일러가 예외처리를 하지 않으므로 3개의 함수가 반드시 호출된다.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Cat
{
private :
string mName;
int mAge;
public :
Cat() = default;
Cat(string name , int age ) : mName{ move(name) }, mAge{age}
{
cout << mName << "constructor" << endl;
}
~Cat() noexcept
{
cout << mName << "destructor" << endl;
}
//복사 생성자.
Cat(const Cat& other) : mName{ other.mName }, mAge{ other.mAge }
{
cout << mName << "Copy 생성자 " << endl;
}
//이동 생성자.
Cat(Cat && other) noexcept :mName{ move(other.mName) }, mAge{ other.mAge }
{
cout << mName << "이동 생성자 " << endl;
}
Cat& operator=(const Cat & other)
{
if (&other == this)
{
return *this;
}
mName = other.mName;
mAge = other.mAge;
cout << mName << " copy assignment " << endl;
return *this;
}
//이동 대입 생성자.
Cat& operator=(Cat && other) noexcept
{
if (&other == this)
{
return *this;
}
mName = move(other.mName);
mAge = other.mAge;
cout << mName << " move assignment " << endl;
return *this;
}
void print()
{
cout << mName << " " << mAge << endl;
}
};
int main()
{
Cat kitty{"키티", 1};
Cat navi{ "나비", 2 };
kitty = kitty;
kitty = move(kitty);
return 0;
}
-> 이동생성자도 마찬가지
-> 복사 생성자 호출되지 않는 것을 출력창을 통해서 확인할 수 있다.