C++指针数组:删除或删除[]?

Jas*_*per 41 c++ arrays pointers delete-operator

Cosider以下代码:

class Foo
{
    Monster* monsters[6];

    Foo()
    {
        for (int i = 0; i < 6; i++)
        {
            monsters[i] = new Monster();
        }
    }

    virtual ~Foo();
}
Run Code Online (Sandbox Code Playgroud)

什么是正确的析构函数?

这个:

Foo::~Foo()
{
    delete [] monsters;
}
Run Code Online (Sandbox Code Playgroud)

或这个:

Foo::~Foo()
{
    for (int i = 0; i < 6; i++)
    {
        delete monsters[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

我目前有最重要的构造函数,一切都在工作,但当然我看不出它是否恰好泄漏...

就个人而言,我认为考虑到我在做什么,第二个版本更合乎逻辑.无论如何,这样做的"正确"方法是什么?

CB *_*ley 47

delete[] monsters;

是不正确的,因为monsters它不是指向动态分配的数组的指针,它一个指针数组.作为类成员,它将在销毁类实例时自动销毁.

您的其他实现是正确的,因为数组中的指针确实指向动态分配的Monster对象.

请注意,使用当前的内存分配策略,您可能希望声明自己的复制构造函数和复制赋值运算符,以便无意复制不会导致双重删除.(如果要阻止复制,可以将它们声明为私有,而不是实际实现它们.)


Kir*_*sky 39

对于new你应该使用delete.供new[]使用delete[].你的第二个变种是正确的.


Jer*_*fin 11

第二个是在这种情况下是正确的(好吧,最不错的,无论如何).

编辑:"最不错",因为原始代码显示没有充分的理由使用newdelete首先,所以你应该只使用:

std::vector<Monster> monsters;
Run Code Online (Sandbox Code Playgroud)

结果将是更简单的代码和更清晰的责任分离.

  • @Jerry 1) 正确 2) 绝对正确 (2认同)
  • 如果Monster是一个基类并且它不想与其他Foo对象共享它的怪物那么它应该是boost :: ptr_vector <Monster>如果不是那么怪物对象的数组(不是怪物指针). (2认同)

小智 11

为了简化answare,我们来看看以下代码:

#include "stdafx.h"
#include <iostream>
using namespace std;

class A
{
private:
    int m_id;
    static int count;
public:
    A() {count++; m_id = count;}
    A(int id) { m_id = id; }
    ~A() {cout<< "Destructor A "   <<m_id<<endl; }
};

int A::count = 0;

void f1()
{   
    A* arr = new A[10];
    //delete operate only one constructor, and crash!
    delete arr;
    //delete[] arr;
}

int main()
{
    f1();
    system("PAUSE");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出为:析构函数A 1然后崩溃(表达式:_BLOCK_TYPE_IS_VALID(phead-nBlockUse)).

我们需要使用:delete [] arr; 是的,它删除了整个数组,而不只是一个单元格!

尝试使用delete [] arr; 输出为:Destructor A 10 Destructor A 9 Destructor A 8 Destructor A 7 Destructor A 6 Destructor A 5 Destructor A 4 Destructor A 3 Destructor A 2 Destructor A 1

相同的原则是指针数组:

void f2()
{
    A** arr = new A*[10];
    for(int i = 0; i < 10; i++)
    {
        arr[i] = new A(i);
    }
    for(int i = 0; i < 10; i++)
    {
        delete arr[i];//delete the A object allocations.
    }

    delete[] arr;//delete the array of pointers
}
Run Code Online (Sandbox Code Playgroud)

如果我们将使用delete arr而不是delete [] arr.它不会删除数组中的整个指针=>指针对象的内存泄漏!


fre*_*low 6

delete[] monsters绝对是错的.我的堆调试器显示以下输出:

allocated non-array memory at 0x3e38f0 (20 bytes)
allocated non-array memory at 0x3e3920 (20 bytes)
allocated non-array memory at 0x3e3950 (20 bytes)
allocated non-array memory at 0x3e3980 (20 bytes)
allocated non-array memory at 0x3e39b0 (20 bytes)
allocated non-array memory at 0x3e39e0 (20 bytes)
releasing     array memory at 0x22ff38
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,您尝试使用错误的delete(非数组与数组)形式发布,并且调用new时从未返回指针0x22ff38.第二个版本显示正确的输出:

[allocations omitted for brevity]
releasing non-array memory at 0x3e38f0
releasing non-array memory at 0x3e3920
releasing non-array memory at 0x3e3950
releasing non-array memory at 0x3e3980
releasing non-array memory at 0x3e39b0
releasing non-array memory at 0x3e39e0
Run Code Online (Sandbox Code Playgroud)

无论如何,我更喜欢一种手动实现析构函数的设计.

#include <array>
#include <memory>

class Foo
{
    std::array<std::shared_ptr<Monster>, 6> monsters;

    Foo()
    {
        for (int i = 0; i < 6; ++i)
        {
            monsters[i].reset(new Monster());
        }
    }

    virtual ~Foo()
    {
        // nothing to do manually
    }
};
Run Code Online (Sandbox Code Playgroud)