ric*_*cab 5 c++ forward-declaration unique-ptr in-class-initialization
我已经读过了std :: unique_ptr <T>需要知道T的完整定义吗?和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;
};
Run Code Online (Sandbox Code Playgroud)
以下不是:
// 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};
};
Run Code Online (Sandbox Code Playgroud)
错误
$ 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’
Run Code Online (Sandbox Code Playgroud)
编辑:据我所知,这里发生的事情是类内初始化程序意味着能够unique_ptr<A>在声明的时刻初始化AUser.由于类型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)
{ }
Run Code Online (Sandbox Code Playgroud)