使用全局变量初始化不同编译单元中的其他全局变量



我有一个共享库,它导出了一个从全局变量返回字符串的函数,如下所示:

测试.h:

const std::string &test_get_name();

测试.cpp:

static std::string name = "Test";
const std::string &test_get_name() {return name;}

在我的主程序(链接到共享库(中,我定义了一个全局变量(如果它是静态的,它仍然被称为"全局"变量吗?(,它使用该函数来初始化对象:

主.cpp:

#include "test.h"
#include <iostream>
struct TestStruct
{
std::string value;
};
static TestStruct v{test_get_name()};
int main(int argc,char *argv[])
{
std::cout<<v.value<<std::endl;
return 0;
}

据我了解,这应该是未定义的行为,因为在创建结构对象时,变量"name"不一定被初始化,这是正确的吗?如果是这样,如果我将"name"变量移动到"test_get_name"中是否有效?

const std::string &test_get_name()
{
static std::string name = "Test";
return name;
}

您的第二种方法将起作用(第一种方法不安全(,但它会花费您一个线程安全的初始化器。 这具有最小的运行时开销,但它确实生成了相当多的代码,请参阅Godbolt。

如果这困扰你,这个函数生成的代码似乎还不错(gcc 和 clang 都构造了临时内联(:

const std::string test_get_another_name()
{
return "Test 2";
}

当然,static TestStruct v{test_get_another_name()};是安全的。

您可以在上面的 Godbolt 链接中找到test_get_nametest_get_another_name,以便您可以比较这两个函数生成的代码。

函数中的静态变量将在第一次调用函数时初始化,所以是的,它会起作用。

对于string以外的事物,例如具有更多副作用的类,可能会有所不同,因为如果不调用函数,则根本不会构造对象。

最新更新