关于C++ 11:我需要手动删除一个空指针,然后指向另一个具体类型吗?

c++ do I need to manually delete a void* pointer which is then pointing to another concrete type?

假设我有一个指针void* p,那么在一些函数的传入和传出之后,假设p现在指向int。那么我需要手动删除为delete static_cast(p)吗?

在大多数地方,人们说只有当有new的时候,delete才会发生。但是在这种情况下,C++本身不记得释放那个内存吗?


这完全取决于你所指的int是如何分配的,你只需要delete你所指的new

正确(intnewd):

1
2
3
4
5
6
int* a = new int;
void* p = a;

//somewhere later...

delete static_cast<int*>(p);

坏(int自动管理):

1
2
3
4
5
6
int a = 0;
void* p = &a;

//somewhere later...

delete static_cast<int*>(p);

回答注释代码,执行以下操作:

1
2
3
4
int* a = new int;
void* p = a;

delete p;

永远不会好。你不应该通过delete通过void*,这是未定义的行为。

旁注:在现代C++中,你不应该使用EDCOX1 2或EDCOX1 1,坚持智能指针或标准容器。


简短的回答是:"视情况而定"。

In most places people say delete only happen when there is new.

就目前而言,这是真的。为了避免浪费资源并确保正确调用所有析构函数,每个new必须在某个地方由delete平衡。如果代码可以遵循多条路径,则必须确保每个路径都调用delete(如果调用delete是适当的)。

当抛出异常时,可能会变得棘手,这是现代C++程序员通常避免使用EDCOX1 2和EDCOX1 1的原因之一。相反,他们使用智能指针std::unique_ptrstd::shared_ptr,以及助手模板函数std::make_uniquestd::make_shared(参见问题:什么是智能指针,什么时候应该使用它?)实现一种称为RAII的技术(资源获取就是实例化)。

But in this case, it's not …

记住这句话…当存在new时,指针指向的对象不是指针本身。考虑以下代码…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int *a = new int();

void *p = a;

if (SomeTest())
{
   delete a;
}
else
{
   a = nullptr;
}

// This line is needed if SomeTest() returned false
// and undefined (dangerous) if SomeTest() returned true
delete static_cast<int *> (p);

需要最后一行代码吗?

ap所指的对象是通过调用new而创建的,所以delete必须被调用。如果函数SomeTest()返回false,那么a已设置为nullptr,因此对其调用delete不会影响我们创建的对象。这意味着我们确实需要最后一行代码来正确删除在第一行代码中更新的对象。

另一方面,如果函数SomeTest()返回true,那么我们已经通过指针a为对象调用delete。在这种情况下,最后一行代码是不需要的,实际上可能是危险的。

C++标准称,在已经删除的对象上调用EDCOX1×1,导致"未定义的行为",这意味着任何事情都可能发生。看到这样的问题:在双重删除中会发生什么?

does C++ itself remember to release that memory?

不是因为调用new创建的任何内容。当你调用new时,你告诉编译器"我已经得到了这个,我会在适当的时候释放内存(通过调用delete来释放内存)。

do I need to manually delete

是:如果此处需要删除指向的对象,并且只有void *指针是指向该对象的唯一指针。