发布时间:Dec. 29, 2022, 11:50 a.m.编辑:李佳生阅读(696)
假定我们有如下代码,定义了一个没有拷贝构造函数或重载等号的类。
class MyClass : { public: Myclass() {ptr = new int();}; ~MyClass() {delete ptr;}; int *ptr = nullptr; int mem = 0; }; int main() { MyClass c1; MyClass c2 = c1; MyClass c3(c1); MyClass c4; c4 = c1; return 0; }
此时c2等号、c3初始化执行的是编译器默认的拷贝构造函数,c4执行的是编译器默认的等号操作,即大概发生如下动作
c2.mem = c1.mem; c2.ptr = c1.ptr; c3.mem = c1.mem; c3.ptr = c1.ptr; c4.mem = c1.mem; c4.ptr = c1.ptr;
熟悉c/c++的同学此时就能看出问题,对于指针ptr,只传递了地址的数值,这就意味着c2、c3、c4的ptr指向与c1是一样的,虽然编译会通过,但是实际使用时会造成问题: c1 c2 c3 c4析构时,会重复释放相同地址的内存,产生问题。
正确的方法应该是定义拷贝构造函数和重载等号,执行内容的深拷贝,这样成员指针就是地址不同,但是内容相同的内存了,也不会产生上述问题。
class MyClass : { public: Myclass() {ptr = new int[10]();}; ~MyClass() {delete[] ptr;}; MyClass(const MyClass& c) { mem = c.mem; ptr = new int(); *ptr = *c.ptr; } Myclass& operator=(Myclass& c) { if (this != &c) { mem = c.mem; ptr = new int(); *ptr = *c.ptr; } return *this; } int *ptr = nullptr; int mem = 0; };
下一篇:梅尔谱&倒谱&MFCCs