C++ 定义向量类型时转发声明错误?
我正在尽可能多地使用前向声明,以尽量减少编译时间。我注意到,当我向前声明一个类时,该类使用std::vector之类的东西作为成员对象(这里的示例):C++ 定义向量类型时转发声明错误?,c++,forward-declaration,C++,Forward Declaration,我正在尽可能多地使用前向声明,以尽量减少编译时间。我注意到,当我向前声明一个类时,该类使用std::vector之类的东西作为成员对象(这里的示例): myTypeA类 甲级 { A(){}; ~A(){}; std::vector getTypeA(); } 我得到以下错误: microsoft visual studio 9.0\vc\include\vector(1112) : error C2036: 'myTypeA *' : unknown size 1> c:
myTypeA类
甲级
{
A(){};
~A(){};
std::vector getTypeA();
}
我得到以下错误:
microsoft visual studio 9.0\vc\include\vector(1112) : error C2036: 'myTypeA *' : unknown size
1> c:\program files\microsoft visual studio 9.0\vc\include\vector(1102) : while compiling class template member function 'bool std::vector<_Ty>::_Buy(unsigned int)'
1> with
1> [
1> _Ty=myTypeA
1> ]
1> d:\cpp\A.h(15) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1> with
1> [
1> _Ty=myTypeA
1> ]
microsoft visual studio 9.0\vc\include\vector(1112):错误C2036:“myTypeA*”:未知大小
1> c:\program files\microsoft visual studio 9.0\vc\include\vector(1102):编译类模板成员函数“bool std::vector::_Buy(unsigned int)”时
1> 与
1> [
1> _Ty=myTypeA
1> ]
1> d:\cpp\A.h(15):请参阅正在编译的类模板实例化“std::vector”的参考
1> 与
1> [
1> _Ty=myTypeA
1> ]
当我使用#include“myTypeA.h”时,这工作正常,为什么?这是因为编译器需要知道要存储在向量中的类型的大小。如果没有完整的类定义,它就无法知道这一点 另一种方法是存储指向前向声明类型的指针,但是需要管理内存分配和释放 第三种选择是根据前向声明的类型声明
共享的\u ptr
类型,并将其存储在向量中。如错误所示
错误C2036:“myTypeA*”:未知大小
编译器无法通过前向声明知道此类型对象的大小。它只是告诉你它是什么类型的。您需要包含标头以引入类定义,以便编译器可以计算此类型对象的大小
见此简单的答案是,该标准需要一个完整的定义 在类型上实例化模板的任何时候;这是未定义的行为 否则。强制执行此类约束的编译器(g++,当您 使用正确的选项编译)将无法编译。其他人可能会 接受它。(虽然形式上未定义行为,但实际上 要么无法编译,要么按预期工作。) 我有点惊讶微软未能编译这段代码 您发布了,因为它不需要知道任何关于
myTypeA
的信息。这个
如果您正在调用
功能;如果你调用这个函数,你肯定需要一个定义
由于编译器必须实例化副本,因此
构造函数,这反过来意味着复制
myTypeA
实际上,向量可以很容易地实现为处理不完整的类型,有一个很好的理由可以证明标准应该强制执行这一点。唉,从目前的情况来看,标准并没有强制要求它,MSVC的标准库显然在检查这一点(顺便说一下,stdlibc++没有)。指针上的一个词,只有在实际打算共享所有权的情况下,shared_ptr
才是合适的。否则(大多数情况下都应该如此),请使用unique\u ptr
@KonradRudolph。我认为向量的约束之一是元素存储在一个连续的内存块中,但这可能是一种比约束更常见的实现策略。@Nick-向量确实将元素存储在一个连续的块中,但在向量中实际存储某些内容之前,不会分配该块。在这一点上,类型显然必须是完整的。标准可能允许不完整类型的空向量。@Nick模板的成员在使用之前不会实例化。因此,在符合标准的编译器中,很难定义std::vector
不处理不完整的类型,因为它的成员和方法签名只需要引用指针。MSVC可能正在执行人工检查以弥补其缺少两次实例化。@Potatoswatter:我认为最好的方法是使用一个函数作为删除器,该函数在TU中声明为不完整的对象类型,在TU中定义为完整的类型。YMMV:-)如果某个类型(一旦完成)将很容易被破坏,那么您甚至可以使用一个函数作为deleter,该函数只通过未完成类型调用delete
。除非实现者检查,否则我对共享的记忆很模糊,但也许我是在想象。无论如何,这是脆弱的,因为很难强制执行您的不完整类型最终会被破坏。
microsoft visual studio 9.0\vc\include\vector(1112) : error C2036: 'myTypeA *' : unknown size
1> c:\program files\microsoft visual studio 9.0\vc\include\vector(1102) : while compiling class template member function 'bool std::vector<_Ty>::_Buy(unsigned int)'
1> with
1> [
1> _Ty=myTypeA
1> ]
1> d:\cpp\A.h(15) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1> with
1> [
1> _Ty=myTypeA
1> ]