0

我的编程背景是 Java 世界,但我刚刚开始学习 C++。作为一名 Java 程序员,我偶然发现了这个相当微不足道且可能相当愚蠢的问题,这让我感到困惑:

我有一个带有数组的类,该数组通过构造函数中的 new 初始化并在析构函数中删除。现在,当我创建这个类的一个对象并将这个类的另一个对象分配给同一个变量时(至少我认为是这样),当变量离开时,析构函数中的 delete[] 方法似乎被调用了两次范围(在本例中为 main() 函数)(调试器给我一个 _BLOCK_TYPE_IS_VALID 断言失败警告)。

这是为什么?为什么在我将新对象分配给 f 之前不调用解构函数?我怎么能明确地删除 Foo(1)?这里到底发生了什么?

class Foo{
    private:
        int *field;

    public:

    Foo(int size){
       field = new int[size];
    }

   ~Foo(){
       delete[] field;
    }
};


int main(){
    Foo f = Foo(1);
    f = Foo(2);
}
4

2 回答 2

6

C++ 世界中有一种东西叫做三法则

一个类会自动为你生成析构函数复制构造函数赋值运算符

如果您必须手动定义其中一个函数,则可能必须定义所有三个函数。

在您的情况下,您应该定义两个复制函数,以便副本Foo获得自己的副本field。添加这两个函数:

class Foo{

    Foo( const Foo &f ) {
        size = f.size;
        field = new int[size]; 
        std::copy( f.field, f.field + size, field );
    }

   Foo& operator=( const Foo &f ) {
       // Leverage the logic that was already written in the copy constructor
       Foo tmp(f);
       std::swap( *this, temp );
       return *this;
   }
};

请注意,我假设您已存储sizeFoo对象中。无论如何,您可能需要将该信息存储在现实生活中的应用程序中

于 2013-03-18T23:37:14.873 回答
2

你没有遵循三法则,这很糟糕。因为默认的复制构造函数做了一个浅拷贝,所以你所有的自动变量(f和临时变量)都有field指向相同的成员int,当调用析构函数时,它会被多次销毁。

实现一个适当的复制构造函数,或者使用 C++ 习惯用法并一起避免手动管理 - 即使用 astd::vector代替。

于 2013-03-18T23:38:11.523 回答