【问题标题】:Using a global variable to initialize other global variable in different compilation units使用一个全局变量来初始化不同编译单元中的其他全局变量
【发布时间】:2018-06-05 07:20:15
【问题描述】:

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

test.h:

const std::string &test_get_name();

test.cpp:

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

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

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;
}

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

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

【问题讨论】:

  • 这个结构更好的名字是单例。

标签: c++ global-variables compilationunit


【解决方案1】:

您的第二种方法会起作用(第一种方法不安全),但它会花费您threadsafe initialiser。这具有最小的运行时开销,但确实会生成大量代码,see at 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,以便比较这两个函数生成的代码。

【讨论】:

    【解决方案2】:

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

    对于string以外的东西,比如一个有更多副作用的类,可能会有区别,好像函数没有被调用,对象永远不会被构造。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多