如何使用智能指针安全地破坏类到不完整的对象类型?

时间:2013-09-01 15:29:49

标签: c++

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

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

farm.h

class Cow;

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

farm.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:无法删除不完整的类型。我猜这回答了我的问题。

2 个答案:

答案 0 :(得分:4)

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

std::unique_ptr<Cow>使用std::default_delete<Cow>std::default_delete<Cow>::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<Cow>::operator()Cow类型完成的地方被实例化。这意味着需要在这样的地方定义Farm的析构函数。

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

答案 1 :(得分:1)

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