2014-11-05 2 views
3

Если у меня естьДействительно ли волшебная статика гарантирует, что правая сторона выполнена только один раз?

atomic<int> cnt=0; 

int get_int() noexcept 
{ 
    cnt++; 
    return rand(); 
} 

, а затем:

void func() 
{ 
    static const auto value = get_int(); 
} 

Я знаю, что не будет никаких условий гонки на инициализацию value, но я не знаю, если get_int() будет вызываться один раз, или в моем примере будет cnt быть 1 (а не 2, 3, 4 или 5).

Предположим, что несколько потоков введены func() и get_int имеет только 1 контактный телефон в func().

+0

Если вы беспокоитесь о нескольких потоках, вызывающих 'func' сразу, я думаю, вы могли бы использовать что-то вроде' std :: call_once ([] {cnt ++;}); ' – chris

+0

cnt - просто пример, меня действительно беспокоит утечка так как моя реальная функция get_int фактически возвращает указатель на объект, который он выделяет. – NoSenseEtAl

ответ

8

C++ 11 гарантирует, что не будет никакого состояния гонки N3797 - §6.7/4:

Реализация разрешено выполнять ранние инициализации другого переменных блоков-Scope со статической или резьбой длительность хранения при тех же условиях, что реализации разрешено статически инициализировать переменную со статикой или временем хранения потоков в пространстве имен (3.6.2). В противном случае такая переменная равна . Инициализированное первое управление временем проходит через его объявление; такая переменная считается инициализированной по завершении ее инициализации . Если инициализация завершается путем исключения исключения, инициализация не завершена, поэтому она будет снова проверена, когда следующий элемент управления войдет в объявление. Если элемент управления вводит декларацию одновременно, когда переменная инициализируется, параллельное выполнение должно ждать завершения инициализации .9 Если управление повторно вводит декларацию рекурсивно, а переменная имеет значение , поведение не определено. [Пример:

int foo(int i) { 
    static int s = foo(2*i); // recursive call - undefined 
    return i+1; 
} 

- конец пример]

Это не Реентрантный но потокобезопасный. Убедитесь, что не будут других частей кода, которые будут звонить get_int() до func() в любом случае.

+0

Пункт 4 раздела 6.7 цитируется как «6.7/4» или еще лучше, используя теги раздела «[stmt.dcl]/4». Номера разделов меняются по мере развития стандарта, но теги остаются неизменными. – Casey

+0

@Casey Спасибо, также за форматирование. Я боролся с цитатой –

1

get_int() будет вызываться только один раз с этой строки, но с учетом вашего кода get_int() может быть вызван заранее из разных мест в коде.

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