【问题标题】:Initializing a static map using static members使用静态成员初始化静态地图
【发布时间】:2016-06-13 13:43:32
【问题描述】:

尝试初始化静态地图。从我收集到的其他问题中,它必须在头文件之外完成,并且在 c++11 中可以通过统一初始化来完成。但是当我尝试使用另一个静态成员时,我遇到了问题:

foo.h:

#include <map>

class TestSuite {
    static constexpr int x = 3;
    static std::map<int, int> v; 
};

foo.cpp:

#include "foo.h"

std::map<int, int> TestSuite::v = {{x, 5}};

int main() {
    TestSuite t;
}

然后我得到错误

In function `__static_initialization_and_destruction_0(int, int)':
foo.cpp:(.text+0x4b): undefined reference to `TestSuite::x'
collect2: error: ld returned 1 exit status

【问题讨论】:

  • 似乎工作正常,你用什么编译器?
  • 5.2,必须是6.1的新特性

标签: c++ c++11 dictionary static


【解决方案1】:

我无法使用 GCC 6.1.0 重现此问题。但是,它可以在您尝试将引用绑定到您尚未定义的 constexpr 变量的任何时候复制,这可能是您的 std::map 构造函数所做的:

struct Foo {
    static constexpr int i = 42;
};

int main() {
    auto const &p = Foo::i; // undefined reference to `Foo::i'
}

这是因为绑定引用是iODR-use,这需要在链接时存在唯一的定义。

在大多数此类情况下,有一个简单的解决方法,那就是应用一元 +

struct Foo {
    static constexpr int i = 42;
};

int main() {
    auto const &p = +Foo::i; // OK!
}

应用 + 不会 ODR 使用 i,因为只需要它的值,而不是它的标识。然后引用绑定到+返回的临时值,而不是i

【讨论】:

    【解决方案2】:

    您还需要定义TestSuite::x。把它放在你的 cpp 文件中:

    const int TestSuite::x;
    

    【讨论】:

    • 静态初始化顺序惨败有没有发挥作用?
    • @NathanOliver 如果两者在同一个 TU 中,则初始化顺序是明确定义的。
    【解决方案3】:

    另一种解决方案。

    static 成员变量更改为static 成员函数。

    class TestSuite {
        static constexpr int getX() { return 3;}
        static std::map<int, int> v; 
    };
    

    std::map<int, int> TestSuite::v = {{getX(), 5}};
    

    【讨论】:

      猜你喜欢
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 2011-07-18
      • 2015-05-18
      • 1970-01-01
      相关资源
      最近更新 更多