类析构函数中出现错误

3

我刚刚开始编写容器类,但已经遇到了问题:

class Container
{
    private:

    string* BasePointer; // The starting pointer.
    unsigned int Capacity; // The number of values the container can hold.

    public:

    Container() // Default constructor.
    {
        Capacity = 1;
        BasePointer = new string[Capacity];
    }

    ~Container() // Destructor.
    {
        delete BasePointer; // Delete the container to prevent memory leaking.
    }
};

我遇到了错误 Container Classes(26467) malloc: *** error for object 0x100100088: pointer being freed was not allocated。请问我做错了什么?

1
它被称为“析构函数”,而不是“解构函数”。 :) - jalf
5个回答

7
XXX ptr = new XXX[size]应该与数组版本delete [] ptr匹配,而不仅仅是常规的delete
阅读有关C++中的自由存储管理的内容,并像詹姆斯提醒我们的那样,在这种情况下遵循三个法则。请参考C++中的自由存储管理三个法则

正是我所思考的。 - Y.H.
谢谢。[]有语法上的原因吗?它可以包含可选参数或其他内容吗? - Maxpm
1
不,你不需要提供参数。原因是——它的功能与delete不同,因此需要一个不同的名称 ;) - etarion

4

你必须使用delete[]

delete[] BasePointer;

2

其他人已经提到你使用new[]delete不匹配,你必须将delete改为delete[]才能修复它。然而,这只是你问题的第一步。

你还需要实现(或至少声明为私有)拷贝构造函数和拷贝赋值运算符。否则,想想当你执行以下操作时会发生什么:

{
    Container c1;
    Container c2(c1);
}   // c2.~Container(); // frees the memory pointed to by 'BasePointer'
    // c1.~Container(); // also frees the memory pointed to by 'BasePointer'.

由于c1和c2的BasePointer成员指向同一数组,因此会被释放两次。
以下是一些更易于使用的替代方案:
- 考虑在任何可能使用动态分配数组的地方使用std::vector。由于您的类名为Container,我假设您正在尝试实现一个资源拥有的容器,因此可能不想使用它。 - 考虑使用boost::scoped_ptr或std::unique_ptr(如果您的编译器支持)来管理指针的所有权。这两个都抑制了隐式声明的复制构造函数的生成,如果您实际上尝试使用它们,则需要自己实现。 - 即使您正在实现一个容器,仍应利用更基本的容器来为您完成繁重的工作(或者至少重新实现那些基本的容器,以便将繁重的工作整合到一小组实用程序中)。
最后,作为一种风格上的建议,您不需要为容器使用malloc。标准库提供了std::allocator,可用于为对象分配空间并构造对象。

1

嗨,如果你创建了一个数组,你必须使用 delete []BasePointer;


0
更加明确地说,当您使用new创建一个数组类型时,您需要使用delete[]删除指针。
这不仅发生在使用new T[size]时,考虑以下示例:
typedef int T[42];
int* x = new T;
delete[] x; // needs delete[] though you used new without []

一般来说,如果您的对象通过指针持有另一个对象,您应该考虑使用智能指针(例如boost::scoped_array)。这样,您就不需要担心析构、异常抛出时会发生什么、实现赋值操作符和复制构造函数等问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接