close
Пространства имён
Варианты
Действия

Константная инициализация

Материал из cppreference.com
 
 
 
 

Устанавливает начальные значения статических переменных в константу времени компиляции.

Синтаксис

static T & ссылка = constexpr; (1)
static T объект = constexpr; (2)

Объяснение

Константная инициализация выполняется вместо инициализации нулём статических и локальных к потоку (начиная с C++11) объектов и перед всеми другими инициализациями. Только следующие переменные инициализируются константами:

1) Статические или локальные к потоку (начиная с C++11) ссылки, если они привязаны к статическому значению lvalue (до C++11)glvalue (начиная с C++11), к временному объекту (или его подобъекту) (начиная с C++11) или к функции, и если каждое выражение (включая неявные преобразования) в инициализаторе ссылки представляет собой константное выражение.
2) Статический или локальный к потоку (начиная с C++11) объект PODType (до C++11) (не обязательно классового типа), который не инициализируется вызовом конструктора, если объект инициализируется значением или если каждое выражение в его инициализаторе является константным выражением.
3) Статический или локальный к потоку объект классового типа, который инициализируется вызовом конструктора, если конструктор является constexpr и все аргументы конструктора (включая неявные преобразования) являются константными выражениями, и если инициализаторы в списке инициализаторов конструктора и инициализаторы в фигурных скобках или равенства элементов класса содержат только константные выражения.
(начиная с C++11)

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

Примечание

Компилятору разрешается инициализировать другие статические и локальные к потоку (начиная с C++11) объекты, используя константную инициализацию, если она может гарантировать, что значение будет таким же, как если бы следовал стандартный порядок инициализации.

На практике константная инициализация выполняется во время компиляции, а предварительно вычисленные представления объектов сохраняются как часть образа программы (например, в разделе .data). Если переменная инициализирована как const, так и константой инициализацией, её объектное представление может быть сохранено в разделе образа программы, доступном только для чтения (например, в разделе .rodata).

Пример

#include <iostream>
#include <array>

struct S
{
    static const int c;
};

const int d = 10 * S::c; // неконстантное выражение: S::c не имеет предшествующего
                         // инициализатора, её инициализация происходит после const
const int 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 инициализация по умолчанию не могла быть константной
инициализацией (требовались константные инициализаторы)
может

Смотрите также