复制构造函数——用相同的变量按值调用函数两次会导致问题

Copy constructor- calling function by value twice with same variable caused problems?

本文关键字:两次 问题 值调用 构造函数 复制 变量 函数      更新时间:2023-10-16

我被指向以下文章:

http://www.codeproject.com/Tips/78946/C-Copy-Constructor-in-depth

,我们有代码:

class string
{
    // constructor
    string(char* aStr)
    {
        str = new char[sizeof(aStr)];
        strcpy (str,aStr);
    }
    // destructor
    ~string() 
    {
        del str;
    }
    char *getChars(){ return str; }
    char* str;
};

void function (string str)
{
    // do something 
}

void main ()
{
    string str("hello");
    function(str);
    function(str); // program crashes
}

我不明白为什么在main中,第二次调用function会有问题?当然,当str被传递到第一次调用时,这只会是str的副本,因此在function中对str所做的任何事情都不会影响在main中声明的变量str ?

默认复制构造函数对对象进行逐位复制。换句话说,复制的是指针成员,而不是它所指向的对象。如果使用默认构造函数并且只对进行浅拷贝,则两个对象中的指针将指向同一个对象

具体到你的问题:

第一次调用function(str)时一切正常,当函数结束时,堆栈上的输入参数被销毁(这是str的副本,但使用默认的复制构造函数,其指针指向与原始对象相同的位置),并且它的析构函数将被调用,删除指针指向的对象。

第二次调用function(str),当函数结束时,析构函数将尝试释放str中指针所指向的地址,并崩溃。

为了避免这样的问题,应该定义自己的复制构造函数,它正确地复制对象,而不仅仅是指针,执行深度复制。

问题是string类中的str成员是一个指针。这意味着当创建字符串的副本时,该指针的值被复制,但指针的值只是一个内存位置。所以当你调用function(str)时,它是在修改那个位置的内存,即使它没有修改指针的值。

默认情况下,c++只知道如何使用默认复制构造函数对数据进行浅层复制。所以,是的,对function的第一次调用确实对str进行了"复制",但这个复制并不是一个复制,因为被复制的是字符串类的char*实例数据。例如,c++只是复制了一个地址,但不够聪明,无法为新字符串分配空间并复制内容。您必须自己使用自定义复制构造函数来完成。

str的构造函数没有为后续对strcpy的调用分配足够的字节。在那之后,所有的赌注都作废了。一旦解决了这个问题,就可以编写合适的复制构造函数和复制赋值操作符。