【发布时间】:2013-09-25 17:25:13
【问题描述】:
我已阅读 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’
编辑:
据我了解,这里发生的是类内初始化程序意味着能够在声明AUser 时已经初始化unique_ptr<A>。由于unique_ptr<A> 类型实际上是unique_ptr<A, default_delete<A>>,因此能够初始化它意味着能够初始化default_delete<A>。为此,A 必须完全定义。
这个推理中的薄弱环节是假设类内初始化器意味着在类声明时初始化相应数据成员的能力!这似乎是一个直观的不言而喻,因为初始化程序是声明的一部分。但是,如果我在标准中找到明确说明的内容,我会更舒服。否则我仍然可以想到不需要它的实施解决方案。例如,编译器可以简单地采用初始化表达式并将其仅应用于未明确给出属性初始化的构造函数。
那么,任何人都可以向我推荐一个标准部分/摘录,暗示在第二种情况下 A 的完整定义是必要的吗?我在标准中没有找到太多关于类内初始化器的信息(只发现它们被称为“brace-or-equal-initializers of non-static 数据成员”),但与此无关。
【问题讨论】:
-
第二种情况的错误是什么?
-
另外:ideone.com/p2iPsv - 似乎第一个也会导致问题。
-
@KirilKirov 它会导致问题,因为您还没有定义 A 类...
-
@KirilKirov:如果您尝试在没有定义
A的情况下生成可执行文件,您显然会遇到问题。但是,如果您只编译片段(当然假设A的定义将在其他地方提供),您不会。我将使用错误更新原始帖子。 -
@Everybody - 对,对,我的错 :)
标签: c++ forward-declaration unique-ptr in-class-initialization