使用全局变量在不同的编译单元中初始化其他全局变量
Using a global variable to initialize other global variable in different compilation units
我有一个共享库,它导出一个函数,该函数 returns 来自全局变量的字符串,如下所示:
test.h:
const std::string &test_get_name();
test.cpp:
static std::string name = "Test";
const std::string &test_get_name() {return name;}
在我的主程序(链接到共享库)中,我定义了一个全局变量(如果它是静态的,它仍然称为 'global' 变量吗?)它使用该函数来初始化一个对象:
main.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;
}
函数内的静态变量将在第一次调用函数时初始化,所以是的,它会起作用。
对于 string
以外的东西,比如 class 有更多的副作用,可能会有所不同,就好像没有调用函数一样,根本不会构造对象。
你的第二种方法可行(第一种不安全),但会花费你 threadsafe initialiser. This has minimal runtime overhead but it does generate quite a lot of code, see at Godbolt。
如果这让你感到困扰,这个函数生成的代码似乎还不错(gcc 和 clang 都构造了临时内联):
const std::string test_get_another_name()
{
return "Test 2";
}
当然,static TestStruct v{test_get_another_name()};
是安全的。
您会在上面的 Godbolt link 中找到 test_get_name
和 test_get_another_name
,因此您可以比较这两个函数生成的代码。
我有一个共享库,它导出一个函数,该函数 returns 来自全局变量的字符串,如下所示:
test.h:
const std::string &test_get_name();
test.cpp:
static std::string name = "Test";
const std::string &test_get_name() {return name;}
在我的主程序(链接到共享库)中,我定义了一个全局变量(如果它是静态的,它仍然称为 'global' 变量吗?)它使用该函数来初始化一个对象:
main.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;
}
函数内的静态变量将在第一次调用函数时初始化,所以是的,它会起作用。
对于 string
以外的东西,比如 class 有更多的副作用,可能会有所不同,就好像没有调用函数一样,根本不会构造对象。
你的第二种方法可行(第一种不安全),但会花费你 threadsafe initialiser. This has minimal runtime overhead but it does generate quite a lot of code, see at Godbolt。
如果这让你感到困扰,这个函数生成的代码似乎还不错(gcc 和 clang 都构造了临时内联):
const std::string test_get_another_name()
{
return "Test 2";
}
当然,static TestStruct v{test_get_another_name()};
是安全的。
您会在上面的 Godbolt link 中找到 test_get_name
和 test_get_another_name
,因此您可以比较这两个函数生成的代码。