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

Прямая инициализация

Материал из cppreference.com
< cpp‎ | language
 
 
 
 

Инициализирует объект из явного набора аргументов конструктора.

Содержание

[править] Синтаксис

T объект ( аргумент );

T объект ( арг1, арг2, ... );

(1)
T объект { аргумент }; (2) (начиная с C++11)
T ( другой )

T ( арг1, арг2, ... )

(3)
static_cast< T >( другой ) (4)
new T(аргументы, ...) (5)
Класс::Класс() : элемент(аргументы, ...) { ... } (6)
[аргумент](){ ... } (7) (начиная с C++11)

[править] Объяснение

Прямая инициализация выполняется в следующих случаях:

1) Инициализация непустым списком выражений в скобках или списками инициализации в фигурных скобках (начиная с C++11).
2) Инициализация объекта неклассового типа с помощью одного инициализатора, заключённого в фигурные скобки (примечание: типы классов и другие варианты использования списка инициализации в фигурных скобках смотрите в разделе инициализация списком) (начиная с C++11).
3) Инициализация prvalue временным объектом (до C++17)результирующего объекта prvalue (начиная с C++17) с помощью приведения в стиле функции или с помощью списка выражений в скобках.
4) Инициализация prvalue временного объекта (до C++17)результирующего объекта prvalue (начиная с C++17) выражением static_cast.
5) Инициализация объекта с динамической длительностью хранения выражением new с инициализатором.
6) Инициализация базового объекта или нестатического элемента списком инициализаторов конструктора.
7) Инициализация элементов объекта замыкания из переменных, захваченных копированием в лямбда-выражении.

Эффекты прямой инициализации:

  • Если T является типом массива,
  • программа некорректна.
(до C++20)
struct A
{
    explicit A(int i = 0) {}
};
 
A a[2](A(1)); // OK: инициализирует a[0] с помощью A(1) и a[1] с помощью A()
A b[2]{A(1)}; // ошибка: неявная инициализация списком копирования b[1]
              //         из {} выбранного явного конструктора
(начиная с C++20)
  • Если T является типом класса,
  • если инициализатор представляет собой выражение prvalue, тип которого является тем же классом, что и T (игнорируя cv-квалификацию), само выражение инициализатора, а не материализованное из него временное выражение, используется для инициализации целевого объекта.
    (До C++17 компилятор мог исключить конструкцию из prvalue временного объекта в этом случае, но соответствующий конструктор должен быть доступен: смотрите пропуск копирования)
(начиная с C++17)
  • проверяются конструкторы T, и с помощью разрешения перегрузки выбирается наилучшее совпадение. Затем для инициализации объекта вызывается конструктор.
  • иначе, если целевой тип является агрегатным классом (возможно, cv-квалифицированным), он инициализируется, как описано в агрегатной инициализации, за исключением того, что сужающие преобразования разрешены, назначенные инициализаторы не разрешены, временная привязка к ссылке не продлевает время жизни, фигурные скобки не удаляются, а любые элементы без инициализатора инициализируются значением.
struct B
{
    int a;
    int&& r;
};
 
int f();
int n = 10;
 
B b1{1, f()};            // OK, продлевается время жизни
B b2(1, f());            // верно, но висячая ссылка
B b3{1.0, 1};            // ошибка: сужающее преобразование
B b4(1.0, 1);            // верно, но висячая ссылка
B b5(1.0, std::move(n)); // OK
(начиная с C++20)
  • Иначе, если T является неклассовым типом, но исходный тип является классовым, проверяются функции преобразования исходного типа и его базовых классов, если таковые имеются, и путём разрешения перегрузки выбирается наилучшее совпадение. Затем выбранное определяемое пользователем преобразование используется для преобразования выражения инициализатора в инициализируемый объект.
  • Иначе, если T равно bool а исходный тип это