使用相同的变量复制构造函数调用函数两次导致问题?

时间:2013-03-11 21:50:02

标签: c++ copy-constructor

我被指出以下文章:

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的副本,因此strfunction所做的任何操作都不会影响变量{{} 1}}在str中声明?

4 个答案:

答案 0 :(得分:3)

默认的复制构造函数执行对象的逐位复制。换句话说,指针成员被复制,但不是它指向的对象。如果您使用默认构造函数并且仅执行浅复制,则两个对象中的指针将指向同一对象

特定于您的问题:

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

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

要避免此类问题,您应该定义自己的复制构造函数,该构造函数不仅可以正确复制对象,还可以执行深层复制。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

默认情况下,C ++只知道如何使用默认的复制构造函数执行浅层数据复制。所以,是的,对function的第一次调用确实会产生一个"副本" str的{​​{1}},但是这个副本不是副本,因为复制的是字符串类的char*实例数据。也就是说,C ++只是复制地址,但不够智能,无法为新字符串实际分配空间并复制内容。您必须自己使用自定义复制构造函数。

答案 3 :(得分:0)

str的构造函数没有为后续调用strcpy分配足够的字节。之后,所有赌注都已关闭。修复后,编写一个正确的复制构造函数和复制赋值运算符。