Относительно C++03:
Абстрактная машина, определенная стандартом C++03, не содержит формального определения того, что такое поток и каким должен быть результат программы, если к объекту осуществляется одновременный доступ.
Не существует понятия примитив синхронизации, упорядочения операций, выполняемых в разных потоках, гонки данных и так далее. Поэтому по определению каждая многопоточная программа на C++03 содержит неопределенное поведение.
Конечно, на практике реализации обеспечивают задокументированное поведение, но в Стандарте нет ничего, определяющего, каким должно быть это поведение. Поэтому я бы сказал, что это зависит от вашего компилятора.
Остальная часть ответа будет посвящена С++ 11, который определяет семантику параллельных операций.
Относительно C++11:
Гарантируется ли, что generateVar()
будет вызываться только один раз в любом сценарии (если, конечно, используется)?
Нет, ни в каком сценарии.
Инициализация var
гарантированно будет потокобезопасной, поэтому generateVar()
не будет вводиться одновременно, но если исключение будет вызвано generateVar()
или конструктором копирования или конструктором перемещения SomeType
(если SomeType
является UDT, конечно) , тогда повторная попытка инициализации будет предпринята в следующий раз, когда поток выполнения войдет в объявление, что означает, что generateVar()
будет вызван снова.
Согласно параграфу 6.7/4 стандарта C++11 об инициализации переменных области блока с статической продолжительностью хранения:
[...] Если инициализация завершается выдачей исключения, инициализация не завершена, поэтому она будет предпринята снова при следующем входе элемента управления в объявление. Если управление вводит объявление одновременно с инициализацией переменной, параллельное выполнение должно дождаться завершения инициализации. Если элемент управления повторно входит в объявление рекурсивно во время инициализации переменной, поведение не определено. [...]
Относительно вашего следующего вопроса:
Гарантируется ли, что foo вернет одно и то же значение при многократном вызове в любом сценарии?
Если удастся вернуть значение (см. выше), то да.
Есть ли разница в поведении для примитивных или непримитивных типов?
Нет, не существует, за исключением того, что не существует такой вещи, как конструктор копирования или конструктор перемещения для примитивных типов, поэтому также нет риска, что инициализация копированием приведет к возникновению исключения (если, конечно, generateVar()
не выдает).
person
Andy Prowl
schedule
24.05.2013