c ++我是否需要手动删除一个void *指针,然后指向另一个具体类型?

时间:2018-06-13 17:10:28

标签: c++ c++11 pointers

假设我有一个指针void* p,然后在传入和退出函数之后,让我们说p现在指向int。然后我需要手动删除delete static_cast<int*>(p)吗?

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

2 个答案:

答案 0 :(得分:6)

这一切都取决于您指定的int的分配方式,只有deletenew的内容。

正确(intnew'd):

int* a = new int;
void* p = a;

//somewhere later...

delete static_cast<int*>(p);

错误(int自动管理):

int a = 0;
void* p = &a;

//somewhere later...

delete static_cast<int*>(p);

回答评论代码,执行:

int* a = new int; 
void* p = a; 

delete p;

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

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

答案 1 :(得分:2)

简短的回答是:“这取决于”。

  

在大多数地方,人们说delete只会在new时发生。

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

抛出异常时可能会变得棘手,这是Modern C++程序员通常避免使用newdelete的一个原因。相反,他们使用智能指针std::unique_ptrstd::shared_ptr以及辅助模板函数std::make_unique<T>std::make_shared<T>(参见SO问题:What is a smart pointer and when should I use one?)来实现一项技术称为RAII (Resource Acquisition Is Instantiation)

  

但在这种情况下,它不是......

请记住短语 ...当有new 时,指向指针指向指针本身的对象。请考虑以下代码......

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,那么我们已经通过指针delete为对象调用了a。在这种情况下,最后一行代码需要,实际上可能很危险。

C ++标准说,在已经删除的对象上调用delete会导致“未定义的行为”,这意味着可能发生任何。请参阅SO问题:What happens in a double delete?

  

C ++本身是否记得释放那个内存?

不是通过调用new创建的任何内容。当你打电话给new时,你告诉编译器“我已经得到了这个,我会在适当时释放那个记忆(通过调用delete)。”

  

我是否需要手动删除

是:如果指向的对象需要在此删除,void *指针是唯一可用于delete对象的指针。