struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
使用 unique_ptr
也没有帮助:(2)
struct A;
struct B {
B() { std::make_unique<A>(); } // error: due to ~unique_ptr()
};
让我大吃一惊的是,我发现这样写也可以编译通过:(3)
struct A;
struct B {
B() { std::make_unique<A>(); }
};
struct A {}; // OK, when a definition is added **below**
然后我检查了一下,是否对new
有帮助 - 没有:(4)
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
struct A {};
我猜这与模板
有关,事实上:在模板
中包装new
是可以编译的: (5)
template <typename T>
T* my_new() { return new T(); } // OK, when wrapped in template
struct A;
struct B {
B() { my_new<A>(); }
};
struct A {};
为了完整起见,删除A
的定义会再次引发错误:(6)
template <typename T>
T* my_new() { return new T(); } // error: allocation of incomplete type 'A'
struct A;
struct B {
B() { my_new<A>(); }
};
// do note: definition of A removed
这里发生了什么?据我所知,编译器必须知道
A
的大小/定义才能分配它,因此仅声明它是不够的。此外,我认为定义必须在分配之前。
当直接使用new
(1,4)时,这似乎是正确的。但是当包装new
时,显然我是错的(2,3,5,6)。
我找到的可能的解释是:
- 完成类型的检查被延迟到
template
实例化发生时。我认为这是正确的,但在我的情况下,new A()
的直接使用和对my_new<A>()
的调用几乎发生在同一位置。所以这不可能是原因。对吗? - 将不完整的类型用作
template
参数可能是未定义的行为。这是真的吗?即使启用所有警告,编译器也不会抱怨。还比较5和6似乎表明,编译器足够聪明,可以找出定义在下面(从而使类型完整)。
为什么4被认为是不正确的,而5则编译(或者5只是虚假地编译未定义的行为[但是那么3也必须有缺陷,对吧?])?
顺便说一下:使用clang++-3.5.0和g++-4.9.2进行测试
A
的定义后才被实例化,这就是为什么它能够编译通过的原因。 - OmnipotentEntity