【问题标题】:c++ do I need to manually delete a void* pointer which is then pointing to another concrete type?c++ 我是否需要手动删除一个指向另一个具体类型的 void* 指针?
【发布时间】:2018-11-23 08:42:15
【问题描述】:

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

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

【问题讨论】:

  • 你只有deletenew。永远成立!!具有自动记忆的东西将自动处理其记忆,而与您将其投射到的内容无关。
  • 如果您不知道分配的来源,请检查文档中提供的任何内容。它可能会为您管理,并且可能需要您调用 API 函数来释放它。
  • 并非所有 C++ 中的内存都必须释放,原始类型和对象都可能位于堆栈中的某个位置,或者位于全局数据部分中。拥有指向某物的指针并不意味着它需要被释放。
  • 我担心这个问题会助长坏习惯。 void* 在 C++ 中相当不寻常。让 void* 负责对象的生命周期几乎可以肯定是一个设计错误。
  • '假设我有一个指针 void* p' 在现代 c++ 中实际上不需要 void*;在 C 中做不可能的事情是一种 hack,但在所有现代 C++ 代码中,即使它与 C 交互,也不应该使用它们。你的假设被拒绝了;)

标签: c++ c++11 pointers


【解决方案1】:

这完全取决于您所指向的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;

从来没有好吗。你永远不应该通过void*delete,这是未定义的行为。


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

【讨论】:

【解决方案2】:

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

在大多数地方,人们说delete 只有在有new 时才会出现。

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

抛出异常时会变得很棘手,这也是Modern C++ 程序员通常避免使用newdelete 的原因之一。相反,他们使用智能指针 std::unique_ptrstd::shared_ptr 以及辅助模板函数 std::make_unique&lt;T&gt;std::make_shared&lt;T&gt;(参见 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 创建的,因此必须在 something 上调用 delete。如果函数SomeTest() 返回false,那么a 已设置为nullptr,因此在其上调用delete 不会影响我们创建的对象。这意味着我们确实需要最后一行代码来正确删除在第一行代码中更新的对象。

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

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

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

不适用于通过调用new 创建的任何内容。当您调用 new 时,您是在告诉编译器“我已经得到了这个,我将在适当的时候释放该内存(通过调用 delete)”。

是否需要手动删除

是:如果指向的对象需要在此处删除,并且void * 指针是您可以使用的唯一指向delete 对象的指针

【讨论】:

    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    相关资源
    最近更新 更多