复制构造函数混淆

Copy constructor confusion

本文关键字:构造函数 复制      更新时间:2023-10-16

有人能解释一下为什么在这个代码中定义了MyClass ( const MyClass & src ) { m_X = src . m_X; }吗?如果没有这行代码,它也能很好地工作,并给出相同的输出,在这种情况下是32。把它放进去和不放进去有什么区别?我读到复制构造函数是自动生成的,但当你在类中定义了指针时,你应该定义它,但在这种情况下我不明白为什么。

以下代码:

#include <iostream>
using namespace std;
class MyClass
{
public:
    MyClass ( int x ) : m_X ( new int ( x ) ) {}
    MyClass ( const MyClass &src ) 
    {
        m_X = src.m_X; 
    }
    void  print ( void ) const 
    { 
        cout << *m_X; 
    }
private:
    int * m_X;
};

int main ( void )
{
    MyClass a ( 32 ), c = a;
    c.print ();
    return 0;
}

默认的复制构造函数和您的复制构造函数执行成员复制(或浅层复制)。在这种情况下,您有一个指针,其值是数据所在的地址。这个地址是复制的。

正如在其他帖子中所指出的,你需要更好地管理指针。

编译器生成的一个(以及您的)的问题是它复制了指针。现在有两个指针c.m_xa.m_x,它们都指向同一个堆分配的对象。谁拥有它?如果你删除了a,它应该删除它分配的内存(你错误地没有这样做),但c仍然指向它,会发生什么?

因此,出现了std::shared_ptr。它是为这种情况设计的,它执行Right Thing By Magic

std::shared_ptr<int> m_X 替换int * m_X

获得相同输出的原因是您正在像编译器一样进行浅层复制。仅仅复制指针是不够的。您需要创建一个新指针,然后将其值设置为要复制的内容的副本。一个合适的构造函数看起来像

MyClass ( const MyClass & src ) : m_X(new int(*src.m_X) {}

现在,副本有自己的独立指针,该指针具有相同的值。

还要注意,您需要一个析构函数来删除内存,并且作为默认复制赋值操作符的适当复制赋值操作符将执行与默认复制构造函数相同的操作。