我已阅读Is std::unique_ptr<T> required to know the full definition of T?和Forward declaration with 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’
编辑:
据我所知,这里发生的事情是,类内初始化器意味着能够在声明unique_ptr<A>
时初始化AUser
。由于unique_ptr<A>
类型实际上是unique_ptr<A, default_delete<A>>
,因此能够初始化它意味着能够初始化default_delete<A>
。而且,为此,A
必须完全定义。
这种推理中的薄弱环节是假设类内初始化器意味着在声明类的时刻初始化相应数据成员的能力!这似乎是一个直观的自我证据,因为初始化程序是声明的一部分。但如果我在标准中明确指出这一点,我会更舒服。否则我仍然可以想到不需要它的实现解决方案。例如,编译器可以简单地获取初始化表达式并仅在未明确给出属性初始化的构造函数中应用它。
那么,任何人都可以向我推荐标准部分/摘录,这意味着在第二种情况下需要完整定义A吗?我对标准中的类内初始化器没有太多了解(只发现它们被称为“支撑或等于初始化器的非静态 数据成员“),但与此无关。
答案 0 :(得分:0)
第二种情况在AUser
定义 [/不正确]的位置生成默认析构函数[错误] (在这种情况下,它实际上是在处理完整代码后完成的)。与AUser
中的构造函数的定义相同。
在任何情况下,您都需要在同一个编译单元中提供A
的定义。那么也许这样的事情会让你满意吗?
#include <memory>
class A;
class AUser
{
std::unique_ptr<A> m_a;
AUser();
};
class A
{
// ...
};
AUser::AUser()
: m_a(nullptr)
{ }