Tho*_* B. 6 c++ destructor smart-pointers incomplete-type c++11
我读过有关不完整类型的unique_ptr和Checked Delete.但是当使用智能指针或至少是C++ 11的智能指针的一个子集时,检查 - 删除是否已过时?
请使用以下代码:
class A;
class B
{
public:
std::auto_ptr<A> autoPtr;
std::unique_ptr<A> uniquePtr;
std::shared_ptr<A> sharedPtr;
A* rawPtr;
B();
~B(){delete rawPtr;}
};
class A
{
public:
~A(){std::cout << "~A" << std::endl;}
};
B::B()
{
autoPtr = std::auto_ptr<A>(new A());
uniquePtr = std::unique_ptr<A>(new A());
sharedPtr = std::shared_ptr<A>(new A());
rawPtr = new A();
}
B b;
Run Code Online (Sandbox Code Playgroud)
当定义B的析构函数时,A的类型仍然不完整.据我所知[C++ 11标准@ [expr.delete]],删除原始指针是未定义的行为.在我的机器上,gcc 4.8显示了一些关于此的警告但是编译并且A的析构函数没有被正确调用.
但智能指针呢?正如我所读,unique_ptr和shared_ptr必须符合c ++ 11标准.但是两个链接文档都说明了auto_ptr不起作用.但至少用我的gcc 4.8也auto_ptr正确调用析构函数,没有任何警告.这仍然是未定义的行为,gcc是不是很好?
简而言之:根据C++ 11标准,四个成员变量中的哪一个可以保证使用它后来定义的析构函数来适当地破坏它们的A指针?
最后:如果我只使用unique_ptr和shared_ptr并且永远不会自己调用"删除",我是否安全并且永远不需要再考虑"已删除"?
重要shared_ptr的是当您将指针传递给 时,类型是否完整shared_ptr(通常应该是完整的,因为您刚刚创建了A)。此时,shared_ptr将创建某种需要完整类型的删除器,并将其存储起来,以便当引用计数降至零时可用(即使这种情况发生在A不完整的文件中)。
重要unique_ptr的是调用时类型是否完整default_delete,这通常位于unique_ptr析构函数中(但也可以位于其reset()成员或赋值运算符中)。
与不完整类型一起使用auto_ptr只是未定义的。
回答标题中的问题:标准要求这样做,shared_ptr并将unique_ptr拒绝编译尝试删除不完整类型的代码。这并不能保证 100% 的安全,因为如果没有虚拟析构函数,这样做unique_ptr<base>(new derived)仍然可能有未定义的行为。base
我相信允许代码编译的原因是 GCC 在文件末尾实例化模板,并且在定义完成B之前不需要内联析构函数。如果您将和的定义放在与变量不同的单独文件中,那么您会发现当被销毁时,它不会正确删除(事实上它甚至不应该编译,因为销毁调用并且标准说需要一个完整的类型或程序格式错误)。bAAB::Bbunique_ptrAbbdefault_delete
可移植的解决方案是确保A在定义析构函数的地方完整B,因此不要内联定义析构函数 ifA在所有文件中不完整。