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对象.
请注意,使用当前的内存分配策略,您可能希望声明自己的复制构造函数和复制赋值运算符,以便无意复制不会导致双重删除.(如果要阻止复制,可以将它们声明为私有,而不是实际实现它们.)
Jer*_*fin 11
第二个是在这种情况下是正确的(好吧,最不错的,无论如何).
编辑:"最不错",因为原始代码显示没有充分的理由使用new或delete首先,所以你应该只使用:
std::vector<Monster> monsters;
Run Code Online (Sandbox Code Playgroud)
结果将是更简单的代码和更清晰的责任分离.
小智 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.它不会删除数组中的整个指针=>指针对象的内存泄漏!
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)