1

我被指出以下文章:

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因此对 inside 所做的任何事情strfunction不会影响在 ? 中str声明的变量main

4

4 回答 4

3

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

具体到您的问题:

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

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

为避免此类问题,您应该定义自己的复制构造函数,它不仅正确复制指针,还正确复制对象,执行深度复制。

于 2013-03-11T21:56:01.153 回答
2

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

于 2013-03-11T21:56:09.347 回答
1

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

于 2013-03-11T21:59:06.413 回答
0

的构造函数str没有为后续调用分配足够的字节strcpy。在那之后,所有的赌注都被取消了。修复后,编写适当的复制构造函数和复制赋值运算符。

于 2013-03-12T04:11:37.977 回答