0

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

测试.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;
}

据我了解,这应该是未定义的行为,因为在创建 struct 对象时,变量“name”不一定被初始化,对吗?如果是这样,如果我在“test_get_name”中移动“name”变量是否有效?:

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

2 回答 2

1

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

如果这让您感到困扰,那么此函数生成的代码似乎还不错(gcc 和 clang 都构造了临时内联):

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

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

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

于 2018-06-05T09:29:39.807 回答
1

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

对于 a 以外的东西string,例如具有更多副作用的类,可能会有所不同,就好像函数没有被调用一样,对象将永远不会被构造。

于 2018-06-05T07:37:32.003 回答