Big Three(拷贝构造,拷贝复制,析构)
class String
{
public:
String (const char* cstr = 0); // 构造函数,默认初值为0
String (const String& str); // 接受的值为类本身,因此为拷贝构造函数
String& operator=(const String& str); // = 号重载,拷贝赋值函数
~String(); // 析构函数,类死亡时自动调用
char* get_c_str() const { return m_data; }
private:
char* m_data;
}
int main()
{
String s1();
String s2("hello");
String s3(s1); // 拷贝构造,类还未存在
cout << s3 << endl;
s3 = s2; // 拷贝赋值,类已经存在
cout << s3 << endl;
}inline
String::String(const char* cstr = 0)
{
if (cstr) { // 指定初值
m_data = new char[strlen(cstr) + 1]; // 分配传进来的长度+ '\0' 的空间
strcpy(m_data, cstr); // 复制
}
else { // 未指定初值
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::~String()
{
delete[] m_data; // 将原来分配的内存释放
}1. String p1("hello"); //栈中分配内存
2. String p2 = String("hello"); //栈中分配内存,跟方法1相同,是方法1的完整模式
3. String *p3 = new String("hello"); //堆中分配内存**
方法1、2中都是在栈中分配内存,在栈中内存由系统自动的去分配和释放,释放的顺序也和栈一样,后定义的先释放。
**
**
而使用new创建的指针对象是在堆中分配内存,当不需要该对象时,需要我们手动的去释放,否则会造成内存泄漏。
**
深拷贝,浅拷贝
如果类中有指针成员,则必须写拷贝构造和拷贝赋值函数。
假设 指针a -> "hello", 指针b -> "world",当执行 b = a 时,则变成 b 指向 a,造成 "world" 无人指向,发生了内存泄漏,而"hello" 被 a 和 b 同时指向的情况,那么将来一旦改变 a ,b 也会发生改变。那么,这种拷贝称之为 “浅拷贝”。
深拷贝即为我们自己写的拷贝函数:
inline
String::String(const String& str) // 拷贝构造
{
m_data = new char[ strlen(str.m_data) + 1 ];
strcpy(m_data, str.m_data);
}
inline
String& String::operator=(const String& str) // 拷贝赋值
{
if(this == &str) // 有可能是自己赋值给自己(比如引用),如果不写这句,那么delete就是它自己,下面全错
return *this;
delete[] m_data; // 先将自己删除
m_data = new char[ strlen(str.m_data) + 1 ]; // 重新创建和右边一样大的空间
strcpy(m_data, str.m_data); // 重新赋值
return *this;
}
京公网安备 11010502036488号