【问题标题】:How to safely destruct class with smart pointer to incomplete object type?如何使用指向不完整对象类型的智能指针安全地破坏类?
【发布时间】:2013-09-04 18:40:56
【问题描述】:

我担心使用带有智能指针的不完整类型以及如何删除指针。下面的代码安全吗?我认为不会,因为 main.cpp 会生成 Farm 的默认析构函数,它不会看到完整的类型。为了安全起见,我认为我应该创建一个看到完整类型的非内联析构函数。对吗?

如果我在 Farm 中使用 std::vector<Cow> 也一样吗?

农场.h

class Cow;

struct Farm
{
    Farm();
    // ~Farm();
    std::unique_ptr<Cow> cow;
};

农场.cpp

#include "cow.h"
// cow now complete

Farm::Farm()
{
    cow.reset(new Cow);
}

// Farm::~Farm() {}

main.cpp

#include "farm.h"

int main()
{
    Farm farm;
}

编辑:我尝试在没有析构函数的情况下使用 Visual Studio 进行编译,它显示错误 C2338:无法删除不完整的类型。我想这回答了我的问题。

【问题讨论】:

  • 请注意,使用 auto_ptr,代码编译:-/
  • @Jarod:是的,而且默默地做错事。
  • @Jarod42: 使用auto_ptr 的代码很糟糕,因为Farm 的默认析构函数使用auto_ptr 的析构函数,它只对不完整类型delete 执行Cow。如果Cow 的实际析构函数不平凡,则它具有UB,否则有效。由于编译器无法分辨它是哪一个(没有Cow 的定义),它继续输出代码。

标签: c++


【解决方案1】:

我认为你的代码不应该编译(而且它不在 gcc 中)

std::unique_ptr&lt;Cow&gt; 使用std::default_delete&lt;Cow&gt;,而std::default_delete&lt;Cow&gt;::operator() 应该无法实例化不完整类型Cow

另见Is it true that a unique_ptr declaration, unlike a auto_ptr declaration, is well-defined when its template type is of an incomplete type?

所以你是对的:你需要确保 default_delete&lt;Cow&gt;::operator()Cow 类型完整的地方被实例化。也就是说Farm的析构函数需要在这样的地方定义。

我刚刚注意到您的主题说“智能指针”,而问题指定unique_ptr。对于shared_ptr,答案会有所不同,因为std::shared_ptr&lt;Cow&gt;::reset() 是一个函数模板,它捕获传递给它的指针的(静态)类型并存储一个删除器。因此,对于shared_ptr,您所需要的只是对reset 的调用具有完整的Cow 类型——析构函数的位置无关紧要。

【讨论】:

  • 谢谢。但是 shared_ptr 什么时候需要完整的类型呢?
  • @NeilKirk:在推断删除器的地方:-reset(),来自指针类型的构造函数和赋值运算符。如果您在这些情况下指定删除器,则 shared_ptr 永远不需要完整类型,只有您的自定义删除器需要。当然还有任何使用operator-&gt;operator* 的结果的人;-)
  • shared_ptr 适用于不完整的类型,但 unique_ptr 不适用
【解决方案2】:

Farm 的默认析构函数将包含 unique_ptr 的析构函数,其中将包含 Cow 的析构函数。即使在编译时没有可用的定义,也会完成此调用。预计链接器会在事后将事物连接起来。

【讨论】:

  • 我试过了,我得到编译器错误 C2338:无法删除不完整的类型
猜你喜欢
  • 2011-08-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多