Использование глобальной переменной для инициализации другой глобальной переменной в разных единицах компиляции

У меня есть общая библиотека, которая экспортирует функцию, которая возвращает строку из глобальной переменной следующим образом:

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

Насколько я понимаю, это должно быть неопределенным поведением, потому что переменная name не обязательно инициализируется еще при создании объекта struct, это правильно? Если это так, было бы правильно, если бы я переместил переменную name в «test_get_name» ?:

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

0

Решение

Ваш второй метод будет работать (первый небезопасен), но это будет стоить вам Потокобезопасный инициализатор. Это имеет минимальные накладные расходы, но генерирует довольно много кода, увидеть на Годболт.

Если это вас беспокоит, код, сгенерированный этой функцией, выглядит не так уж плохо (и gcc, и clang создают временную строку):

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

И тогда, конечно, static TestStruct v{test_get_another_name()}; безопасно.

Вы найдете оба test_get_name а также test_get_another_name в ссылке Godbolt выше, чтобы вы могли сравнить код, сгенерированный двумя функциями.

1

Другие решения

Статическая переменная внутри функции будет инициализирована при первом вызове функции, так что да, она будет работать.

Для других вещей, кроме stringКак и в классе с большим количеством побочных эффектов, может существовать разница, если функция не вызывается, объект никогда не будет создан вообще.

1

По вопросам рекламы [email protected]