#include <iostream>
using namespace std;
class String
{
public:
String()
{
cout << "String() : " << this << endl;
strData = NULL;
len = 0;
}
String(const char *str)
{
cout << "String(const char *) 생성자 호출" << this << endl;
len = strlen(str);
alloc(len);
strcpy(strData, str);
}
//매게변수로 String 클래스 타입을 받는것.
String(const String &ref)
{
cout << "String(String &ref) 생성자 호출" << endl;
len = ref.len;
alloc(len);
strcpy(strData, ref.strData);
}
~String()
{
cout << "~String(): " << this << endl;
release();
strData = NULL;
}
//복사 대입 연산자
String &operator=(const String &rhs)
{
cout << "String &operator = (const String&) : " << this << endl;
if (this != &rhs)
{
release();
len = rhs.len;
alloc(len);
strcpy(strData, rhs.strData);
}
return *this;
}
char *GetstrData() const
{
return strData;
}
int Getlen() const
{
return len;
}
//복사 생성자
void SetStrData(const char *str)
{
cout << "void setStrData(const char*) : " << this << ", " << str << endl;
len = strlen(str);
alloc(len);
strcpy(strData, str);
}
private:
void alloc(int len)
{
strData = new char[len + 1];
cout << "strData allocated : " << (void *)strData << endl;
}
void release()
{
delete[] strData;
if (strData)
cout << "strData released: " << (void *)strData << endl;
}
char *strData;
int len;
};
String getName()
{
cout << " ===== 2 =====" << endl;
// res 라는 객체 생성
String res("Jinchoel");
cout << " ===== 3 =====" << endl;
return res;
}
int main()
{
//매게변수가 없는 생성자를 가진 객체 'a' 생성
String a;
cout << " ===== 1 =====" << endl;
// a라는 변수에 getName 함수의 결과를 할당.
// 복사 대입 연사자 ('=') 호출.
a = getName();
cout << " ===== 4 =====" << endl;
}
해당 코드 실행시 a가 대입연산자를 통해서 함수(getName())의 결과를 할당받으면서 '복사생성자' 실행됨.
getName 함수 내에서 return res 실행 후 res 는 소멸.
그러면 어떻게 a는 getName이 반환하는 res를 할당받을 수 있을까 ?
따라서 getName이 리턴되는 순간 새로운 retrun값을 받는 새로운 변수 필요. -> 이름이 없음 : 임시객체
res 가 임시객체 안으로 들어감.
그 후 임시객체가 a로 흘러들어감.
임시객체가 a로 복사가되면 임무를 끝마쳤으므로 임시객체는 사라짐.
총 2번의 깊은 복사 이루어짐 ( res -> 임시객체 , 임시객체 -> a)
하지만 res, 임시객체는 a=getName() 코드 실행시 사라질 불필요한 객체들.
따라서 객체간의 복사를 깊은복사가 아닌 '얕은복사'로 이루어지게 만듦.
'이동'이라는 컨셉을 가지고 얕은 복사 손쉽게 구현하기
r-value
int f() { retrun 5; }
&&r (r-value 참조자)
이동생성자 & 이동 대입 연산자
----> 이동시멘틱의 기본적 원리
정리 : res, 임시객체는 r-value로 간주되기 때문에 String(String &&rhs), String & operatr=(String &&rhs)((r-value를 매게변수로 받음)) 에서 볼 수 있는 &&rhs와 같은 매게변수가 호출이된다.