如何使用指向不完整对象类型的智能指针安全地销毁类

How to safely destruct class with smart pointer to incomplete object type?

本文关键字:安全 指针 智能 类型 何使用 对象      更新时间:2023-10-16

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

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

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

我认为您的代码不应该编译(在gcc中也不应该编译)

std::unique_ptr<Cow>使用std::default_delete<Cow>,而std::default_delete<Cow>::operator()应该无法实例化不完整的类型Cow

另请参阅unique_ptr声明与auto_ptr声明不同,当其模板类型为不完整类型时,是否确实定义良好?

所以您是对的:您需要确保default_delete<Cow>::operator()Cow类型完整的地方被实例化。这意味着Farm的析构函数需要在这样一个地方定义。

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

Farm的默认析构函数将包括unique_ptr的析构函数,其中包括Cow的析构因子。即使在编译时没有可用的定义,也会执行此调用。链接器将被期望在事实发生后将事情连接起来。