假设我有一个指针void* p
,然后在传入和退出函数之后,让我们说p现在指向int
。然后我需要手动删除delete static_cast<int*>(p)
吗?
在大多数地方,人们说delete
只会在new
时发生。但在这种情况下,它不是,但C ++本身是否记得释放那个内存?
答案 0 :(得分:6)
这一切都取决于您指定的int
的分配方式,只有delete
您new
的内容。
正确(int
为new
'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 ++中,你真的不应该使用new
或delete
,坚持使用智能指针或标准容器。
答案 1 :(得分:2)
简短的回答是:“这取决于”。
在大多数地方,人们说
delete
只会在new
时发生。
到目前为止,这是真的。为了避免浪费资源并确保正确调用所有析构函数,每个new
必须由delete
在某处平衡。如果您的代码可以遵循多个路径,则必须确保每个路径都调用delete
(如果调用delete
是合适的话)。
抛出异常时可能会变得棘手,这是Modern C++程序员通常避免使用new
和delete
的一个原因。相反,他们使用智能指针std::unique_ptr
和std::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);
需要最后一行代码吗?
a
和p
都指向的对象是通过调用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
对象的指针。