Default constructors
Un constructor predeterminado es un constructor que puede ser invocado sin argumentos.
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
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
|
(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
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) .
-
Tno tiene funciones miembro virtuales. -
Tno tiene clases base virtuales.
|
(desde C++11) |
-
Cada base directa de
Ttiene un constructor por defecto trivial.
|
(until C++26) |
|
(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 |