无法在std :: map成员变量中分配具有前向声明值的类

时间:2014-04-16 20:41:44

标签: c++ compiler-errors forward-declaration stdmap

test.h

#ifndef TEST_H
#define TEST_H

#include <map>
struct Incomplete;

class Test {
     std::map<int, Incomplete> member;
public:
    Test();
    int foo() { return 0; }
};

#endif

test.cpp

#include "test.h"
struct Incomplete {};
Test::Test() {}

main.cpp

#include "test.h"

int main() {
    Test test;
    return test.foo();
}

g ++ 4.7在写struct Incomplete时给出了g++ main.cpp test.h -o main.o向前声明的错误。

但是,如果我将std::map<int, Incomplete> member更改为std::map<int, Incomplete*> member,则main.o会进行编译。为什么是这样?

3 个答案:

答案 0 :(得分:4)

  

为什么会这样?

因为C ++标准库容器未定义为使用不完整的成员类型。 This is by design 1 - 但它可以说是一个错误(可能会在将来的C ++版本中更改)。 Boost.Containers库修复此问题。

带指针的代码有效,因为指向不完整类型的指针本身就是一个完整的类型。但是,这显然会极大地改变你的类型的语义(特别是,谁管理内存?),并且通常不好用它作为替代。


1 值得指出的是,该文章声称您在技术上无法实施std::map来处理不完整类型。但是,这种说法是错误的。

答案 1 :(得分:0)

当您转发声明类型时,您基本上声明存在具有该名称的类型,仅此而已。编译器不知道它的大小,成员等。它被称为不完整类型,除了声明指针或引用之外不能用于任何其他内容。这是可能的,因为指针的大小,无论其类型如何,在同一平台上都是相同的。

答案 2 :(得分:0)

前向声明意味着“此类/结构/稍后将在代码中的任何内容”。容器需要知道结构存储记录的大小。在技​​术方面,您使用的是不完整类型

由于指针在大多数机器上都是固定大小(x64通常有8个字节的指针),因此在编译时不需要查看结构的完整定义,因为您不需要“计算”多少在地图中为该结构保留的空间:您只需要指针所需的空间。