C++ 一个类型何时被认为是完整的?

C++ 一个类型何时被认为是完整的?,c++,boost,smart-pointers,incomplete-type,scoped-ptr,C++,Boost,Smart Pointers,Incomplete Type,Scoped Ptr,考虑以下代码片段。boost::scoped_ptr的析构函数在主函数末尾调用。析构函数使用boost::checked_delete来释放封装的小部件指针 #include <boost/scoped_ptr.hpp> #include <iostream> class Widget; Widget *make_widget(); int main() { boost::scoped_ptr<Widget> sp(make_widget());

考虑以下代码片段。boost::scoped_ptr的析构函数在主函数末尾调用。析构函数使用boost::checked_delete来释放封装的小部件指针

#include <boost/scoped_ptr.hpp>
#include <iostream>

class Widget;
Widget *make_widget();

int main()
{  
  boost::scoped_ptr<Widget> sp(make_widget());
  // std::cout << sizeof(Widget) << std::endl;
}

class Widget
{
public:
  Widget() {}
  ~Widget() { std::cout << "Widget destructor called." << std::endl; }
};

Widget *make_widget()
{
  return new Widget;
}
#包括
#包括
类控件;
Widget*make_Widget();
int main()
{  
boost::作用域的_ptr sp(make_widget());
//标准::cout
5.3.5删除
[expr.Delete]
5如果要删除的对象在删除点具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为未定义

因此,您当然会期望它是UB,因为
Widget::~Widget()
是非常重要的,并且您会期望boost中的安全保护出错

现在,让我们挖得更高:

2.2翻译阶段
[lex.Phases]
8个翻译单元和实例化单元组合如下:[注:…]检查每个翻译单元,以生成所需实例化列表。[注:这可能包括明确要求的实例化(14.7.2)。-结束注]所需模板的定义位于。是否需要提供包含这些定义的翻译单元的源,由实现定义。[注:实现可以将足够的信息编码到翻译单元中,以确保此处不需要源。-结束注]执行所有必需的实例化以生成实例化单元。[注意:这些与翻译单元类似,但不包含对未实例化模板的引用,也不包含模板定义。-结束注意]如果任何实例化失败,则程序的格式不正确

您将通过翻译的阶段保存:

翻译翻译单元,然后实例化模板…

为什么没有选中删除失败?选中删除只有在类型完整时才能正确工作。这正是这种情况下的一种保护措施。感谢您让我思考这些问题。因此,粗略地说,实例化可能会推迟到对翻译单元。对于这种实现,在翻译单元中的任何位置定义一个前向声明的类型,就像在前向声明之后使定义在任何地方都可用一样。这也是我通过将类def移出TU@CppNoob:不可以。所有符合要求的实现必须推迟模板实例化直到翻译结束。;和你一样,我也希望
check_delete
能够捕捉到不完整类型的使用,所以我很惊讶这个编译有
sizeof
的注释。@MatthieuM.:得到了解释。我想区别在于你是否编写了
struct SP{~SP(){depene ptr;}/*.*/}
struct SP{~SP();/*…*/};
。如果析构函数不是内联的,则在调用时不需要知道它,因此也不需要
ptr
的类型。