命名空间中的C ++全局变量

时间:2016-04-14 11:18:33

标签: c++ namespaces

我已经看到很多关于此的问题,但没有一个包含有关如何编译此特定用例的代码的说明。我运行以下命令:g++ main.cpp c.cpp testobj.cpp -o main,但运行此命令会给我一个Segmentation fault (core dumped)。当我在main中的main.cpp方法中使用print语句并删除所有TestObj代码时,它确实有效。

这是分配C::test常量的正确方法吗?

main.cpp中:

#include "c.h"
#include "testobj.h"

TestObj testobj;

int main() {
    return 0;
}

c.h:

#ifndef CONSTANTS
#define CONSTANTS

#include <string>

namespace C {
    extern std::string test;
}
#endif

c.cpp:

#include "c.h"

namespace C {
    std::string test = "test";
}

testobj.h:

#ifndef TESTOBJ
#define TESTOBJ

class TestObj {
public:
    TestObj();
};

#endif

testobj.cpp:

#include "testobj.h"
#include <iostream>
#include "c.h"

TestObj::TestObj() {
    std::cout << C::test << std::endl;
}

2 个答案:

答案 0 :(得分:3)

这是由全局静态变量的初始化顺序引起的。它未定义,称为static initialization order fiasco。当TestObj::TestObj(使用C::test时,它尚未构建。

解决它的常用方法是将全局静态变量移动到函数局部静态变量中,即:

const std::string getTestString() {
    static std::string test = "test";
    return test;
}

现在,当你调用getTestString()时,将构造测试变量,并且它将完成一次。此外,由于函数中的静态变量的C ++ 11初始化保证是线程安全的。

答案 1 :(得分:2)

虽然单个translation unit中全局变量的初始化顺序已明确定义,但翻译单元之间的顺序不是

因此,如果testobj源文件中的main.cpp对象在C::test对象之前初始化,那么您确实会有奇怪的行为。

如果您有多个翻译单元,每个单元都有全局变量,那么您就不能依赖它们之间的初始化顺序。