Константная инициализация
Устанавливает начальные значения статических переменных в константу времени компиляции.
Содержание |
[править]Синтаксис
static T& ссылка= constexpr; | (1) | ||||||||
static Tобъект= constexpr; | (2) | ||||||||
[править]Объяснение
Константная инициализация выполняется вместо инициализации нулём статических и локальных к потоку(начиная с C++11) объектов и перед всеми другими инициализациями. Только следующие переменные инициализируются константами:
3) Статический или локальный к потоку объект классового типа, который инициализируется вызовом конструктора, если конструктор является constexpr и все аргументы конструктора (включая неявные преобразования) являются константными выражениями, и если инициализаторы в списке инициализаторов конструктора и инициализаторы в фигурных скобках или равенства элементов класса содержат только константные выражения. | (начиная с C++11) |
Эффекты константной инициализации такие же, как эффекты соответствующей инициализации, за исключением того, что гарантируется, что она будет завершена до любой другой инициализации статического или локального к потоку(начиная с C++11) объекта, и она может быть выполнена во время компиляции.
[править]Примечание
Компилятору разрешается инициализировать другие статические и локальные к потоку(начиная с C++11) объекты, используя константную инициализацию, если она может гарантировать, что значение будет таким же, как если бы следовал стандартный порядок инициализации.
На практике константная инициализация выполняется во время компиляции, а предварительно вычисленные представления объектов сохраняются как часть образа программы (например, в разделе .data
). Если переменная инициализирована как const
, так и константой инициализацией, её объектное представление может быть сохранено в разделе образа программы, доступном только для чтения (например, в разделе .rodata
).
[править]Пример
#include <iostream>#include <array> struct S {staticconstint c;}; constint d =10* S::c;// неконстантное выражение: S::c не имеет предшествующего// инициализатора, её инициализация происходит после constconstint S::c=5;// константная инициализация, которая гарантированно// произойдёт первой int main(){std::cout<<"d = "<< d <<'\n';std::array<int, S::c> a1;// OK: S::c константное выражение// std::array<int, d> a2; // ошибка: d не является константным выражением}
Вывод:
d = 50
[править]Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
CWG 441 | C++98 | ссылки не могут быть инициализированы константно | сделаны константно инициализируемыми |
CWG 1489 | C++98 | было неясно, может ли инициализация значением объекта быть константной инициализацией | может |
CWG 1747 | C++98 | привязка ссылки к функции не может быть константной инициализацией | может |
CWG 1834 | C++11 | привязка ссылки к xvalue не может быть константной инициализацией | может |
CWG 2026 | C++98 | было указано, что инициализация нулём всегда происходит первой, даже до константной инициализации | нет инициализации нулём, если применяется константная инициализация |
CWG 2366 | C++98 | инициализация по умолчанию не могла быть константной инициализацией (требовались константные инициализаторы) | может |