5

我已阅读是否需要 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;
};

以下没有:

// 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 吗?我在标准中没有找到太多关于类内初始化器的信息(只发现它们被称为“非静态数据成员的大括号或相等初始化器”),但与此无关。

4

1 回答 1

0

第二种情况在定义[/incorrect]的地方AUser生成默认析构函数[incorrect ](在这种情况下,它实际上是在处理整个代码之后完成的)。与内部构造函数的定义相同AUser

无论如何,您仍然需要A在同一编译单元中提供定义。所以也许像这样的东西会让你满意?

#include <memory>

class A;

class AUser
{
  std::unique_ptr<A> m_a;
  AUser();
};


class A
{
  // ...
};


AUser::AUser() 
  : m_a(nullptr)
{ }
于 2013-09-20T22:56:30.053 回答