重新分配变量,删除调用了两次(C++)

Reassigning variable, delete called twice (C++)

本文关键字:两次 C++ 调用 新分配 分配 变量 删除      更新时间:2023-10-16

我的编程背景是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);
}

在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;
   }
};

请注意,我假设您已将size存储在Foo对象中。您可能需要在实际应用程序中存储这些信息

您没有遵守三条规则,这很糟糕。因为默认的复制构造函数执行浅层复制,所以所有的自动变量(f和临时变量(都有指向同一个intfield成员,在调用析构函数时会多次销毁该成员。

实现一个正确的复制构造函数,或者使用C++习惯用法并避免手动管理——即使用std::vector