我读过Howard Hinnant(Is std::unique_ptr<T> required to know the full definition of T?)的答案,然后这个答案(How is a template instantiated?)我正在思考。如果你有这样的课程
class Something {
Something();
~Something();
class Impl;
std::unique_ptr<Impl> impl;
};
当编译类时,unique_ptr
将被实例化(正如我从上面的其他答案中得出的那样)。那么为什么以后没有定义类Impl
可以呢?实例化不会要求Impl
的析构函数存在吗?
注意以下内容旨在澄清上述问题。
当编译器查看类Something
的定义时,我正在思考它的方式。它将看到嵌套类Impl
的声明,然后它将看到unique_ptr<Impl>
的声明,并在那时。它将使用unique_ptr
实例化模板Impl
。并且该实例化代码将包含对Impl
的析构函数的调用。由于此时我们的代码包含对不完整类的析构函数的调用,上面的代码如何安全?
答案 0 :(得分:1)
The accepted answer to the first question包含一个用例表,其中需要Impl
的完整定义。
在您的情况下,编译器隐式生成以下成员函数:
所有这些都需要Impl
的完整定义。
如果您明确声明这些功能并将其定义在Impl
的完整定义可用的位置,那么您就可以了。
<强>更新强>
它将看到嵌套类
Impl
的声明,然后它将看到unique_ptr<Impl>
的声明,并在那时。它将使用unique_ptr
实例化模板Impl
。
这在某种程度上是正确的。并非unique_ptr
的所有成员函数都将在那时实例化。
该实例化代码将包含对
Impl
的析构函数的调用。
不正确。只有在需要时,编译器才会生成std::unique_ptr<Impl>
的析构函数(或实例化)。那个地方是Something
的析构函数。
Something
的析构函数需要std::unique_ptr<Impl>
的析构函数
std::unique_ptr<Impl>
的析构函数需要Impl
的完整定义。
换句话说,Impl
的完整定义必须对Something
的析构函数可见。
<强> PS 强>
有关模板实例化的更多信息,请访问Template instantiation details of GCC and MS compilers。
答案 1 :(得分:0)
如果您尝试编译上述代码并创建Something对象,则会显示错误消息:
Semantic issue:
memory:2523:27: Invalid application of 'sizeof' to an incomplete type
'Something::Impl'
简而言之,代码是无法编译的,在这种情况下没有必要考虑安全性。