Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 定义向量类型时转发声明错误?_C++_Forward Declaration - Fatal编程技术网

C++ 定义向量类型时转发声明错误?

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:

我正在尽可能多地使用前向声明,以尽量减少编译时间。我注意到,当我向前声明一个类时,该类使用std::vector之类的东西作为成员对象(这里的示例):

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>        ]