2016-05-12 3 views
0

В целом я хотел бы спросить, где хранятся локальные переменные функции статической функции? если статическая переменная используется внутри статической функции, переменная только инициализируется один раз?Статическая переменная C++ внутри статической функции элемента

Пожалуйста, обратитесь к коду ниже

std::string const CONST1 = "const1"; 
std::string const CONST2 = "const2"; 
std::string const CONST3 = "const3"; 

class Test 
{ 
    public: 
    static const std::vector<std::string> GetSomeMap(); 
} 

const std::vector<std::string> Test::GetSomeMap() 
{ 
    static std::vector<std::string> SomeMap = boost::assign::list_of(CONST1)(CONST2)(CONST3); 

return SomeMap; 

} 

Из приведенного выше кода, есть преимущество того, чтобы объявить SomeMap как статические? (Я ожидаю, что это будет только инициализируется один раз)

+2

Он инициализируется один раз, но обратите внимание, что вы возвращаете копию карты вместо ссылки на нее. Возможно, вы захотите это исправить. – Blacktempel

+0

можно считать, что RVO (Оптимизация возвращаемого значения) не будет выполняться? – BubbleBoy

+0

Иногда авторы классов избегают использования статической переменной-члена, заменяя ее статической локальной переменной внутри статической функции-члена (но функция должна возвращать ссылку или указатель, в отличие от вашего примера). Это делается либо для того, чтобы избежать попыток с инициализацией в нескольких единицах перевода, либо во избежание необходимости инициализации статического члена внутри файла реализации (для определения класса только для заголовка). –

ответ

3

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

Ответ «да».
Это также «да» для static переменных регулярных, то есть не static, функций-членов.
Это также «да» для static переменных функций, не являющихся членами.

0

Статические переменные внутри функций (независимо от типа функции): stored in the "DATA" segment, как и global variables. Таким образом, вы можете сказать, что таким образом функции статические переменные похожи на глобальные, просто они доступны только по имени в ограниченной области (тело функции).

0

Если переменная является статической, она хранится в куче. Если переменная является членом статической функции, она хранится в статической локальной переменной. И они только инициализируются один раз.

0

В целом, я хотел бы спросить, где хранятся локальные переменные члена статической функции?

Зависит. Статический постоянный простой старый тип данных может храниться в сегменте данных только для чтения. Статическая переменная с постоянным инициализатором может храниться в сегменте данных, а статическая переменная, требующая динамической инициализации, может храниться в сегменте BSS.

если статическая переменная используется внутри статической функции, то переменная только инициализируется один раз?

Да. В этом случае SomeMap будет инициализирован, первый элемент управления проходит через его объявление.

Нулевая инициализация (8.5) всех локальных объектов со статической продолжительностью хранения (3.7.1) выполняется перед любой другой инициализации происходит. Локальный объект типа POD (3.9) со статической продолжительностью хранения, инициализированный константами-константами , инициализируется до того, как его блок будет введен первым. Реализации разрешено выполнять раннюю инициализацию других локальных объектов со статической продолжительностью хранения при тех же условиях, что реализация разрешена для статической инициализации объекта со статической продолжительностью хранения в области пространства имен (3.6.2). В противном случае такой объект инициализируется, когда первый контроль проходит через его объявление; такой объект считается инициализированным после завершения его инициализации. Если инициализация завершается, вызывая исключение , инициализация не завершена, поэтому она будет проверена снова, в следующий раз управление войдет в объявление .

Раздел 6.7, пункт 4 ИСО/МЭК 14882: 2003 (E) (извините, у меня нет более поздней копии стандартных удобного)

Из приведенной выше коды , есть преимущество того, чтобы объявить SomeMap как статические (я ожидаю, что это будет только инициализируется один раз)

Да есть преимущество, чтобы объявить его статическим - это будет инициализирован только один раз и только инициализируется, если это используемый. Если Test :: GetSomeMap никогда не вызывается, SomeMap никогда не инициализируется.

Как указано выше, B @ Blacktempel утверждает, что Test :: GetSomeMap должен возвращаться ссылкой, чтобы удалить любые сомнения относительно создания дополнительных копий SomeMap.

Вы также должны учитывать, что вы берете на себя затраты на создание трех строк (CONST1, CONST2 и CONST3), каждый из которых может выделять кучную память для хранения копии своих инициализаторов строки константного выражения («const1», «const2», «const3»). Кроме того, если вы вызываете Test :: GetSomeMap, вы также берете на себя стоимость инициализации вектора SomeMap, который также может выделять кучную память для хранения копий строк.

Если вы беспокоитесь об использовании памяти и накладных расходах инициализации и вы действительно хотите статический постоянный массив строк, просто объявить один, например, так:

static const char* const * GetSomeMap(void) { 
    static const char* const SomeMap[] = {"const1", "const2", "const3"}; 
    return SomeMap; 
} 

SomeMap будет потреблять минимум памяти без дополнительных затрат инициализации (и быть полностью неизменным).

Смежные вопросы