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

C++ C++;命名空间中的全局变量,c++,namespaces,C++,Namespaces,我已经看到了很多关于这方面的问题,但是没有一个包括关于如何为这个特定用例编译代码的解释。我运行以下命令:g++main.cpp c.cpp testobj.cpp-o main,但运行此命令会导致分段错误(内核转储)。当我在main.cpp中的main方法中有print语句并删除所有TestObj代码时,它确实起作用 这是分配C::test常量的正确方法吗 main.cpp: #include "c.h" #include "testobj.h" TestObj testobj; int m

我已经看到了很多关于这方面的问题,但是没有一个包括关于如何为这个特定用例编译代码的解释。我运行以下命令:
g++main.cpp c.cpp testobj.cpp-o main
,但运行此命令会导致
分段错误(内核转储)
。当我在
main.cpp
中的
main
方法中有print语句并删除所有
TestObj
代码时,它确实起作用

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

main.cpp:

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

TestObj testobj;

int main() {
    return 0;
}
#ifndef CONSTANTS
#define CONSTANTS

#include <string>

namespace C {
    extern std::string test;
}
#endif
#include "c.h"

namespace C {
    std::string test = "test";
}
#ifndef TESTOBJ
#define TESTOBJ

class TestObj {
public:
    TestObj();
};

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

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

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

TestObj testobj;

int main() {
    return 0;
}
#ifndef CONSTANTS
#define CONSTANTS

#include <string>

namespace C {
    extern std::string test;
}
#endif
#include "c.h"

namespace C {
    std::string test = "test";
}
#ifndef TESTOBJ
#define TESTOBJ

class TestObj {
public:
    TestObj();
};

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

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

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

TestObj testobj;

int main() {
    return 0;
}
#ifndef CONSTANTS
#define CONSTANTS

#include <string>

namespace C {
    extern std::string test;
}
#endif
#include "c.h"

namespace C {
    std::string test = "test";
}
#ifndef TESTOBJ
#define TESTOBJ

class TestObj {
public:
    TestObj();
};

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

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

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

TestObj testobj;

int main() {
    return 0;
}
#ifndef CONSTANTS
#define CONSTANTS

#include <string>

namespace C {
    extern std::string test;
}
#endif
#include "c.h"

namespace C {
    std::string test = "test";
}
#ifndef TESTOBJ
#define TESTOBJ

class TestObj {
public:
    TestObj();
};

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

TestObj::TestObj() {
    std::cout << C::test << std::endl;
}
#包括“testobj.h”
#包括
#包括“c.h”
TestObj::TestObj(){

std::cout虽然在单个变量中全局变量的初始化顺序定义得很好,但转换单元之间的顺序却没有定义

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


如果有多个转换单元,每个单元都有全局变量,则不能依赖它们之间的初始化顺序。

虽然一个单元中全局变量的初始化顺序定义得很好,但转换单元之间的顺序没有定义

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


如果有多个转换单元,每个单元都带有全局变量,则不能依赖它们之间的初始化顺序。

这是由全局静态变量的初始化顺序造成的。它未定义,称为。当
TestObj::TestObj(
使用
C::test
)时,它尚未构造

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

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

现在,当您调用
getTestString()时
测试变量将被构造,并且只执行一次。另外,由于C++11函数中静态变量的初始化保证线程安全。

这是由全局静态变量的初始化顺序引起的。它未定义,称为.When
TestObj::TestObj(
使用
C::test
——它还没有构建

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

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

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

I将
TestObj TestObj
的声明更改为
TestObj*TestObj
并将初始化移动到
main()< >代码>方法,通过执行<代码> *TestObj= TestObjor()/代码>?@ MARTIJNN2008是的,如果您考虑使用指针安全的话:在初始化所有全局变量后,
main
函数将始终被调用。通过执行
*TestObj=TestObj()操作,我保存将
TestObj TestObj
的声明更改为
TestObj*TestObj
,并将初始化移动到
main()
方法?@ MaTijnn2008:是的,如果您考虑使用指针安全。
main
函数总是在所有全局变量初始化后被调用。此外,在静态变量的构造函数中使用std::cout是不安全的,因为std::cout本身就是静态变量,我们也依赖于它的初始化。@IgorSemenov我没有考虑它,因为C++11看起来它是固定的-而且,usi静态变量构造函数中的ng std::cout是不安全的,因为std::cout本身就是静态变量,我们也依赖于它的初始化。@IgorSemenov我没有考虑过它,因为C++11看起来它是固定的-