Namespaces
Variants

Default constructors

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
Default constructor
Copy constructor
Move constructor (C++11)
Templates
Miscellaneous

Un constructor predeterminado es un constructor que puede ser invocado sin argumentos.

Contenidos

Sintaxis

class-name  ( parameter-list  (opcional) ); (1)
class-name  ( parameter-list  (opcional) ) function-body (2)
class-name  () = default; (3) (desde C++11)
class-name  ( parameter-list  (opcional) ) = delete; (4) (desde C++11)
class-name  :: class-name  ( parameter-list  (opcional) ) function-body (5)
class-name  :: class-name  () = default; (6) (desde C++11)
class-name - la clase cuyo constructor predeterminado se está declarando
parameter-list - una lista de parámetros donde todos los parámetros (excepto parameter packs ) (since C++11) tienen default arguments
function-body - el function body del constructor predeterminado

Explicación

1) Declaración de un constructor predeterminado dentro de la definición de clase.
2-4) Definición de un constructor predeterminado dentro de la definición de clase.
3) El constructor predeterminado está explícitamente predeterminado.
4) El constructor predeterminado está eliminado.
5,6) Definición de un constructor por defecto fuera de la definición de la clase (la clase debe contener una declaración (1) ).
6) El constructor predeterminado está explícitamente predeterminado.

Los constructores por defecto se invocan durante las inicializaciones por defecto y las inicializaciones de valor .

Constructor predeterminado declarado implícitamente

Si no hay un constructor declarado por el usuario o una plantilla de constructor para un tipo de clase, el compilador declarará implícitamente un constructor predeterminado como un inline public miembro de su clase.

El constructor por defecto declarado implícitamente (o predeterminado en su primera declaración) tiene una especificación de excepciones como se describe en especificación dinámica de excepciones (hasta C++17) especificación noexcept (desde C++17) .

Constructor predeterminado definido implícitamente

Si el constructor está implícitamente declarado (hasta C++11) el constructor por defecto implícitamente declarado o explícitamente definido como default no está definido como eliminado (desde C++11) , es implícitamente definido por el compilador cuando odr-used o needed for constant evaluation o cuando es explícitamente definido como default después de su primera declaración (desde C++11) .

Si un constructor por defecto de una clase tipo union T es trivial, entonces para cada union U que es ya sea T o una union anónima miembro de T , si el primer miembro variante (si existe) de U tiene tipo de duración implícita , el constructor por defecto de T inicia la duración de ese miembro si no es el miembro activo de su union.

(desde C++26)

Un (hasta C++26) En caso contrario, un (desde C++26) constructor predeterminado definido implícitamente tiene el mismo efecto que un constructor definido por el usuario con cuerpo vacío y lista de inicializadores vacía. Es decir, llama a los constructores predeterminados de las bases y de los miembros no estáticos de esta clase. Los tipos de clase con un constructor proporcionado por el usuario vacío pueden tratarse de manera diferente a aquellos con un constructor predeterminado definido implícitamente durante la inicialización de valor .

Si esto satisface los requisitos de un constexpr constructor (hasta C++23) constexpr function (desde C++23) , el constructor generado es constexpr .

Si están presentes algunos constructores definidos por el usuario, el usuario aún puede forzar la generación automática de un constructor predeterminado por el compilador que de otro modo se declararía implícitamente con la palabra clave default .

(desde C++11)


Constructor por defecto eliminado

El constructor por defecto declarado implícitamente o establecido explícitamente para la clase T se define como eliminado si se cumple alguna de las siguientes condiciones:

  • T tiene un miembro de datos no estático de tipo referencia sin un inicializador por defecto.
  • T es una clase no- union y (desde C++26) tiene un miembro de datos no estático no variante no- const-default-constructible de tipo calificado const (o posiblemente un array multidimensional del mismo) sin un inicializador de miembro por defecto.
  • T es una union y todos sus miembros variantes son de tipo calificado const (o posiblemente un array multidimensional del mismo).
  • T es una clase no-union y todos los miembros de cualquier anonymous union miembro son de tipo calificado const (o posiblemente un array multidimensional del mismo).
(hasta C++26)
  • Dado un tipo de clase M , T tiene un subobjeto potencialmente construido obj de tipo M (o posiblemente un array multidimensional del mismo), y se cumple alguna de las siguientes condiciones:
  • M tiene un destructor que está eliminado o es inaccesible desde el constructor por defecto , y ya sea que obj sea no variante o obj tenga un inicializador de miembro por defecto (desde C++26) .
  • Se cumplen todas las siguientes condiciones:
  • obj no es un miembro de datos no estático con un inicializador por defecto.
  • obj no es un miembro variante de una union donde otro miembro de datos no estático tiene un inicializador por defecto (hasta C++26) .
  • La resolución de sobrecarga aplicada para encontrar el constructor por defecto de M no resulta en un candidato utilizable , o en el caso de que obj sea un miembro variante, selecciona una función no trivial (hasta C++26) .

Si no hay constructores definidos por el usuario presentes y el constructor por defecto declarado implícitamente no es trivial, el usuario aún puede inhibir la generación automática de un constructor por defecto definido implícitamente por el compilador con la palabra clave delete .

(desde C++11)

Constructor por defecto trivial

El constructor predeterminado para la clase T es trivial si se cumplen todas las siguientes condiciones:

  • El constructor está implícitamente-declarado (hasta C++11) no user-provided (desde C++11) .
  • T no tiene funciones miembro virtuales.
  • T no tiene clases base virtuales.
  • T no tiene miembros no estáticos con inicializadores predeterminados.
(desde C++11)
  • Cada base directa de T tiene un constructor por defecto trivial.
  • Cada miembro no estático de tipo clase (o arreglo del mismo) tiene un constructor por defecto trivial.
(until C++26)
  • Ya sea que T sea una unión, o cada miembro no estático no variante de tipo clase (o arreglo del mismo) tiene un constructor por defecto trivial.
(since C++26)

Un constructor por defecto trivial es un constructor que no realiza ninguna acción. Todos los tipos de datos compatibles con el lenguaje C (tipos POD) son trivialmente construibles por defecto.

Constructor predeterminado elegible

Un constructor por defecto es elegible si es declarado por el usuario o bien declarado implícitamente y definible.

(until C++11)

Un constructor por defecto es elegible si no está eliminado.

(since C++11)
(until C++20)

Un constructor por defecto es elegible si se satisfacen todas las siguientes condiciones:

(since C++20)

La trivialidad de los constructores por defecto elegibles determina si la clase es un implicit-lifetime type , y si la clase es un trivially copyable type .

Notas

Macro de prueba de características Valor Std Característica
__cpp_trivial_union 202502L (C++26) Relajación de los requisitos de trivialidad para las funciones miembro especiales de uniones

Ejemplo

struct A
{
    int x;
    A(int x = 1): x(x) {} // constructor por defecto definido por el usuario
};
struct B : A
{
    // B::B() está definido implícitamente, llama a A::A()
};
struct C
{
    A a;
    // C::C() está definido implícitamente, llama a A::A()
};
struct D : A
{
    D(int y) : A(y) {}
    // D::D() no está declarado porque existe otro constructor
};
struct E : A
{
    E(int y) : A(y) {}
    E() = default; // explícitamente predeterminado, llama a A::A()
};
struct F
{
    int& ref; // miembro de referencia
    const int c; // miembro constante
    // F::F() está definido implícitamente como eliminado
};
// el constructor de copia declarado por el usuario (ya sea proporcionado, eliminado o predeterminado)
// previene la generación implícita de un constructor por defecto
struct G
{
    G(const G&) {}
    // G::G() está definido implícitamente como eliminado
};
struct H
{
    H(const H&) = delete;
    // H::H() está definido implícitamente como eliminado
};
struct I
{
    I(const I&) = default;
    // I::I() está definido implícitamente como eliminado
};
int main()
{
    A a;
    B b;
    C c;
//  D d; // error de compilación
    E e;
//  F f; // error de compilación
//  G g; // error de compilación
//  H h; // error de compilación
//  I i; // error de compilación
}

Informes de defectos

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

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 1353 C++11 las condiciones donde los constructores por defecto implícitamente declarados son
definidos como eliminados no consideraban tipos de arreglos multidimensionales
considerar estos tipos
CWG 2084 C++11 los inicializadores de miembros por defecto no tenían efecto sobre si
un constructor por defecto definido por defecto de una unión es eliminado
previenen que el constructor por defecto
definido por defecto sea eliminado
CWG 2595 C++20 un constructor por defecto no era elegible si existe
otro constructor por defecto que está más restringido
pero no satisface sus restricciones asociadas
puede ser elegible en este caso
CWG 2871 C++98 un constructor por defecto sería implícitamente declarado
incluso si existe una plantilla de constructor declarada por el usuario
no hay declaración implícita
en este caso

Véase también