我担心使用带有智能指针的不完整类型以及如何删除指针。以下代码是否安全?我认为不会,因为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:无法删除不完整的类型。我猜这回答了我的问题。
答案 0 :(得分:4)
我不认为你的代码应该编译(并且它不在gcc中)
std::unique_ptr<Cow>
使用std::default_delete<Cow>
,std::default_delete<Cow>::operator()
无法为不完整类型Cow
实例化。
所以你是对的:你需要确保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
的析构函数。即使在编译时没有可用的定义,也将完成此调用。预计链接器会在事后连接起来。