9.11 대입 연산자 오버로딩, 깊은 복사, 얕은 복사
#include <iostream>
#include <cassert>
using namespace std;
class MyString
{
//private:
public:
char *m_data = nullptr;
int m_length = 0;
public:
MyString(const char *source = "")
{
assert(source);
m_length = std::strlen(source) + 1; // 문자열의 마지막이라는 것을 뜻하게 위한 nullptr을 위한 자리
m_data = new char[m_length];
for (int i=0; i < m_length; ++i)
m_data[i] = source[i];
m_data[m_length - 1] = '\0';
}
~MyString()
{
delete[] m_data;
}
char* getString() { return m_data; }
int getLength() { return m_length; }
};
int main()
{
MyString hello("Hello");
cout << (int*)hello.m_data << "\n"; // 문자열로 인식하기 때문에 인트형으로 변환
cout << hello.getString() << "\n";
{
MyString copy = hello; // 기본적으로 들어있는 복사 생성자는 값만 복사하기 때문에 주소도 복사해준다.(얕은 복사) new로 할당된 메모리가 없다는
// 뜻! 근데 이 scope를 벗어나면 destructor로 인해 delete됨
cout << (int*)copy.m_data << "\n";
cout << copy.getString() << "\n";
}
cout << hello.getString() << "\n"; // copy에서 동적 할당 메모리를 삭제해버렸기 때문에 이상한 값이 떠버리게 된다.
return 0;
}
#include <iostream>
#include <cassert>
using namespace std;
class MyString
{
//private:
public:
char *m_data = nullptr;
int m_length = 0;
public:
MyString(const char *source = "")
{
assert(source);
m_length = std::strlen(source) + 1;
m_data = new char[m_length];
for (int i=0; i < m_length; ++i)
m_data[i] = source[i];
m_data[m_length - 1] = '\0';
}
// MyString (const MyString &source) = delete; // copy constructor를 만들 여력이 없을 때 얕은 복사를 막기 위해 사용. 하지만 그냥 차선 책일뿐
MyString( const MyString &source)
{
cout << "Copy constructor " << "\n";
m_length = source.m_length;
if (source.m_data != nullptr)
{
m_data = new char[m_length]; // 주소를 다시 할당하고 다시 복사 => 깊은 복사(주소를 복사하는 것이 아니라 내용을 복사)
for (int i=0; i < m_length; ++i)
m_data[i] = source.m_data[i];
}
else
m_data = nullptr;
}
MyString& operator = (const MyString & source) // 대입 연산자
{
// shallow copy 라면
//this->m_data = source.m_data;
//this->m_length = source.m_length;
// 이런식으로 값만 할당. 이것이 기본 constructor
cout << "Assignment operator " << "\n";
if (this == &source) // prevent self-assignment 아무것도 하지 못하게 막는다.
return *this
delete[] m_data;
m_length = source.m_length;
if (source.m_data != nullptr)
{
m_data = new char[m_length];
for (int i=0; i < m_length; ++i)
m_data[i] = source.m_data[i];
}
else
m_data = nullptr;
}
~MyString()
{
delete[] m_data;
}
char* getString() { return m_data; }
int getLength() { return m_length; }
};
int main()
{
MyString hello("Hello");
//cout << (int*)hello.m_data << "\n";
//cout << hello.getString() << "\n";
//{
// MyString copy = hello;
// cout << (int*)copy.m_data << "\n";
// cout << copy.getString() << "\n";
//}
//cout << hello.getString() << "\n"; // copy와 hello가 가지고 있는 주소가 다르기 때문에 제대로된 값이 나온다.
// MyString str1(hello); // MyString str1 = hello; 와 기능상 같아서 copy constructor라는 것을 알 수 있다.
MyString str1 = hello; // copy constructor. 최초로 만들어지는 순간이기 때문
MyString str2; // 그냥 생성자.
str2 = hello; // assignment constructor.
return 0;
}