Namespaces
Variants

Value-initialization

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Это инициализация, выполняемая при создании объекта с пустым инициализатором.

Содержание

Синтаксис

T () (1)
new T () (2)
Class :: Class ( ... ) : member () { ... } (3)
T object {}; (4) (начиная с C++11)
T {} (5) (начиная с C++11)
new T {} (6) (начиная с C++11)
Class :: Class ( ... ) : member {} { ... } (7) (начиная с C++11)

Объяснение

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

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

Во всех случаях, если используется пустая пара фигурных скобок {} и T является агрегатным типом, агрегатная инициализация выполняется вместо value-инициализации.

Если T является типом класса, который не имеет конструктора по умолчанию, но имеет конструктор, принимающий std::initializer_list , выполняется list-initialization .

(since C++11)

Эффекты инициализации значением:

  • Если T является (возможно, cv-квалифицированным) классным типом:
  • В противном случае, если T является типом массива, каждый элемент массива инициализируется по значению.
  • В противном случае объект инициализируется нулями.

Примечания

Синтаксис T object ( ) ; не инициализирует объект; он объявляет функцию, которая не принимает аргументов и возвращает T . Способ value-инициализации именованной переменной до C++11 был T object = T ( ) ; , который value-инициализирует временный объект и затем copy-инициализирует объект: большинство компиляторов оптимизируют копирование в этом случае.

Ссылки не могут быть инициализированы значением по умолчанию.

Как описано в разделе function-style cast , синтаксис T ( ) (1) запрещён, если T обозначает тип массива, тогда как T { } (5) разрешён.

Все стандартные контейнеры ( std::vector , std::list , и т.д.) инициализируют свои элементы по значению при создании с единственным аргументом size_type или при увеличении размера через вызов resize ( ) , если только их аллокатор не изменяет поведение construct .

Пример

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
struct T1
{
    int mem1;
    std::string mem2;
    virtual void foo() {} // гарантирует, что T1 не является агрегатом
}; // неявный конструктор по умолчанию
struct T2
{
    int mem1;
    std::string mem2;
    T2(const T2&) {} // пользовательский конструктор копирования
};                   // нет конструктора по умолчанию
struct T3
{
    int mem1;
    std::string mem2;
    T3() {} // пользовательский конструктор по умолчанию
};
std::string s{}; // класс => инициализация по умолчанию, значение равно ""
int main()
{
    int n{};                // скаляр => обнуляющая инициализация, значение равно 0
    assert(n == 0);
    double f = double();    // скаляр => обнуляющая инициализация, значение равно 0.0
    assert(f == 0.0);
    int* a = new int[10](); // массив => инициализация значением каждого элемента
    assert(a[9] == 0);      //          значение каждого элемента равно 0
    T1 t1{};                // класс с неявным конструктором по умолчанию =>
    assert(t1.mem1 == 0);   //     t1.mem1 обнуляется, значение равно 0
    assert(t1.mem2 == "");  //     t1.mem2 инициализируется по умолчанию, значение равно ""
//  T2 t2{};                // ошибка: класс без конструктора по умолчанию
    T3 t3{};                // класс с пользовательским конструктором по умолчанию =>
    std::cout << t3.mem1;   //     t3.mem1 инициализируется по умолчанию в неопределенное значение
    assert(t3.mem2 == "");  //     t3.mem2 инициализируется по умолчанию, значение равно ""
    std::vector<int> v(3);  // инициализация значением каждого элемента
    assert(v[2] == 0);      // значение каждого элемента равно 0
    std::cout << '\n';
    delete[] a;
}

Возможный вывод:

42

Отчеты о дефектах

Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
CWG 178 C++98 не существовало value-initialization; пустой инициализатор вызывал default-
initialization (хотя new T ( ) также выполняет zero-initialization)
пустой инициализатор вызывает
value-initialization
CWG 543 C++98 value-initialization для объекта класса без каких-либо
user-provided конструкторов была эквивалентна value-
initialization каждого подобъекта (что не обязательно zero-
initialize член с user-provided default constructor)
zero-initializes
весь объект,
затем вызывает
default constructor
CWG 1301 C++11 value-initialization объединений с удаленными
default constructors приводила к zero-initialization
они
default-initialized
CWG 1368 C++98 любой user-provided конструктор вызывал
пропуск zero-initialization
только user-provided
default constructor
пропускает zero-initialization
CWG 1502 C++11 value-initializing объединения без user-provided
default constructor только zero-initialized
объект, несмотря на default member initializers
выполняет default-
initialization после
zero-initialization
CWG 1507 C++98 value-initialization для объекта класса без каких-либо
user-provided конструкторов не проверяла валидность
default constructor когда последний является trivial
валидность trivial
default constructor
проверяется
CWG 2820 C++98 default-initialization после zero-
initialization требовала non-trivial constructor
не требуется
CWG 2859 C++98 value-initialization для объекта класса могла включать
zero-initialization даже если default-initialization
фактически не выбирает user-provided constructor
нет
zero-initialization
в этом случае

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