首页 文章

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

提问于
浏览
2

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

在大多数地方,人们说 delete 只有在 new 时才会发生 . 但在这种情况下,它不是,但C本身是否记得释放那些记忆?

2 回答

  • 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;
    

    永远不会好的 . 你永远不应该 void* ,它是未定义的行为 .


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

  • 2

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

    在大多数地方,人们说删除只会在有新的时候发生 .

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

    抛出异常时会变得棘手,这是程序员通常避免使用 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 时,指向对象指针指向 not 指针本身 . 考虑以下代码......

    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 . 在这种情况下,最后一行代码需要 not ,实际上可能很危险 .

    C标准说在已经删除的对象上调用 delete 导致"undefined behaviour",这意味着任何事情都可能发生 . 见SO问题:What happens in a double delete?

    C本身是否记得释放那段记忆?

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

    我需要手动删除

    是的: if the object pointed to needs to be deleted here and the void * pointer is the only pointer you can use to delete the object .

相关问题