我已经阅读了std::unique_ptr
以下编译:
// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration
class AUser
{
AUser(); // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a;
};
以下不会:
// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration
class AUser
{
AUser(); // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a{nullptr};
};
错误
$ g++ -std=c++11 -c fwd_decl_u_ptr.cpp
In file included from /usr/include/c++/4.7/memory:86:0,
from fwd_decl_u_ptr.cpp:3:
/usr/include/c++/4.7/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A]’:
/usr/include/c++/4.7/bits/unique_ptr.h:173:4: required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A; _Dp = std::default_delete<A>]’
fwd_decl_u_ptr.cpp:9:33: required from here
/usr/include/c++/4.7/bits/unique_ptr.h:63:14: error: invalid application of ‘sizeof’ to incomplete type ‘A’
编辑:据我了解,这里发生的事情是类内初始值设定项意味着能够在声明AUser
的那一刻已经初始化unique_ptr<A>
。由于类型 unique_ptr<A>
实际上是unique_ptr<A, default_delete<A>>
,能够初始化它意味着能够初始化default_delete<A>
。为此,必须完全定义A
。
此推理中的薄弱环节是假设类内初始值设定项意味着在声明类时初始化相应数据成员的能力!这似乎是一个直观的自我证明,因为初始值设定项是声明的一部分。但是,如果我在标准中找到明确说明这一点的内容,我会更舒服。否则,我仍然可以想到不需要它的实现解决方案。例如,编译器可以简单地采用初始值设定项表达式,并仅在未显式给出属性初始化的构造函数中应用它。
那么,谁能给我推荐一个标准部分/摘录,暗示在第二种情况下需要完整定义 A?我在标准中没有找到太多关于类内初始值设定项的信息(只发现它们被称为"非静态的大括号或等于初始值设定项"数据成员"),但与此无关。
第二种情况生成默认析构函数 [不正确] 来代替AUser
定义 [/不正确](在这种情况下,它实际上是在处理整个代码后完成的)。与 AUser
中的构造函数定义相同。
无论如何,您仍然需要在同一编译单元中提供A
的定义。所以也许这样的事情会让你满意?
#include <memory>
class A;
class AUser
{
std::unique_ptr<A> m_a;
AUser();
};
class A
{
// ...
};
AUser::AUser()
: m_a(nullptr)
{ }