拷贝构造,拷贝复制,析构

Big Three(拷贝构造,拷贝复制,析构)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
2
3
4
5
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 也会发生改变。那么,这种拷贝称之为 “浅拷贝”

深拷贝即为我们自己写的拷贝函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}
作者

Benboby

发布于

2020-05-11

更新于

2021-03-07

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×