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

Esta es la inicialización realizada cuando un objeto se construye con un inicializador vacío.

Contenidos

Sintaxis

T () (1)
new T () (2)
Class :: Class ( ... ) : member () { ... } (3)
T object {}; (4) (desde C++11)
T {} (5) (desde C++11)
new T {} (6) (desde C++11)
Class :: Class ( ... ) : member {} { ... } (7) (desde C++11)

Explicación

La inicialización por valor se realiza en estas situaciones:

1,5) cuando se crea un objeto temporal sin nombre con el inicializador que consiste en un par vacío de paréntesis o llaves (since C++11) ;
2,6) cuando un objeto con duración de almacenamiento dinámico es creado por una new expresión con el inicializador consistente en un par vacío de paréntesis o llaves (desde C++11) ;
3,7) cuando un miembro de datos no estático o una clase base se inicializa usando un inicializador de miembro con un par vacío de paréntesis o llaves (desde C++11) ;
4) cuando un objeto con nombre (automático, estático o local de hilo) se declara con el inicializador que consiste en un par de llaves.

En todos los casos, si se utiliza el par de llaves vacío {} y T es un tipo agregado, aggregate initialization se realiza en lugar de value-initialization.

Si T es un tipo de clase que no tiene constructor por defecto pero tiene un constructor que acepta std::initializer_list , se realiza list-initialization .

(since C++11)

Los efectos de la inicialización por valor son:

  • Si T es un tipo clase (posiblemente calificado con cv):
  • De lo contrario, si T es un tipo de arreglo, cada elemento del arreglo es inicializado por valor.
  • De lo contrario, el objeto es inicializado a cero.

Notas

La sintaxis T object ( ) ; no inicializa un objeto; declara una función que no toma argumentos y retorna T . La forma de inicializar por valor una variable nombrada antes de C++11 era T object = T ( ) ; , que inicializa por valor un temporal y luego inicializa por copia el objeto: la mayoría de compiladores optimizan la copia en este caso.

Las referencias no pueden ser inicializadas por valor.

Como se describe en function-style cast , la sintaxis T ( ) (1) está prohibida si T nombra un array type, mientras que T { } (5) está permitida.

Todos los contenedores estándar ( std::vector , std::list , etc.) inicializan por valor sus elementos cuando se construyen con un único argumento size_type o cuando se expanden mediante una llamada a resize ( ) , a menos que su asignador personalice el comportamiento de construct .

Ejemplo

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
struct T1
{
    int mem1;
    std::string mem2;
    virtual void foo() {} // asegura que T1 no sea un agregado
}; // constructor por defecto implícito
struct T2
{
    int mem1;
    std::string mem2;
    T2(const T2&) {} // constructor de copia proporcionado por el usuario
};                   // sin constructor por defecto
struct T3
{
    int mem1;
    std::string mem2;
    T3() {} // constructor por defecto proporcionado por el usuario
};
std::string s{}; // clase => inicialización por defecto, el valor es ""
int main()
{
    int n{};                // escalar => inicialización a cero, el valor es 0
    assert(n == 0);
    double f = double();    // escalar => inicialización a cero, el valor es 0.0
    assert(f == 0.0);
    int* a = new int[10](); // array => inicialización por valor de cada elemento
    assert(a[9] == 0);      //          el valor de cada elemento es 0
    T1 t1{};                // clase con constructor por defecto implícito =>
    assert(t1.mem1 == 0);   //     t1.mem1 es inicializado a cero, el valor es 0
    assert(t1.mem2 == "");  //     t1.mem2 es inicializado por defecto, el valor es ""
//  T2 t2{};                // error: clase sin constructor por defecto
    T3 t3{};                // clase con constructor por defecto proporcionado por el usuario =>
    std::cout << t3.mem1;   //     t3.mem1 es inicializado por defecto a valor indeterminado
    assert(t3.mem2 == "");  //     t3.mem2 es inicializado por defecto, el valor es ""
    std::vector<int> v(3);  // inicialización por valor de cada elemento
    assert(v[2] == 0);      // el valor de cada elemento es 0
    std::cout << '\n';
    delete[] a;
}

Salida posible:

42

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 178 C++98 no existía la inicialización por valor; el inicializador vacío invocaba
inicialización por defecto (aunque new T ( ) también realizaba
inicialización a cero)
el inicializador vacío invoca
inicialización por valor
CWG 543 C++98 la inicialización por valor para un objeto de clase sin constructores
proporcionados por el usuario equivalía a inicializar por valor cada
subobjeto (lo que no necesitaba inicializar a cero un miembro con
constructor por defecto proporcionado por el usuario)
inicializa a cero
todo el objeto,
luego llama al
constructor por defecto
CWG 1301 C++11 la inicialización por valor de uniones con constructores por defecto
eliminados resultaba en inicialización a cero
se realiza
inicialización por defecto
CWG 1368 C++98 cualquier constructor proporcionado por el usuario causaba
que se omitiera la inicialización a cero
solo un constructor por defecto
proporcionado por el usuario
omite la inicialización a cero
CWG 1502 C++11 inicializar por valor una unión sin constructor por defecto
proporcionado por el usuario solo inicializaba a cero el
objeto, a pesar de los inicializadores de miembro por defecto
realiza inicialización
por defecto después de
la inicialización a cero
CWG 1507 C++98 la inicialización por valor para un objeto de clase sin ningún
constructor proporcionado por el usuario no verificaba la validez
del constructor por defecto cuando este es trivial
se verifica la validez del
constructor por defecto
trivial
CWG 2820 C++98 la inicialización por defecto que seguía a la inicialización
a cero requería un constructor no trivial
no requerido
CWG 2859 C++98 la inicialización por valor para un objeto de clase podría involucrar
inicialización a cero incluso si la inicialización por defecto
no selecciona realmente un constructor proporcionado por el usuario
no hay
inicialización a cero
en este caso

Véase también