Lo he visto default
junto a las declaraciones de funciones en una clase. ¿Qué hace?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Lo he visto default
junto a las declaraciones de funciones en una clase. ¿Qué hace?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Respuestas:
Es una nueva característica de C ++ 11 .
Significa que desea utilizar la versión generada por el compilador de esa función, por lo que no necesita especificar un cuerpo.
También puede usar = delete
para especificar que no desea que el compilador genere esa función automáticamente.
Con la introducción de constructores de movimiento y operadores de asignación de movimiento, las reglas para cuando se generan versiones automáticas de constructores, destructores y operadores de asignación se han vuelto bastante complejas. Usar = default
y = delete
facilita las cosas ya que no necesita recordar las reglas: solo dice lo que quiere que suceda.
= delete
es más fuerte: significa que está prohibido usar esa función, aunque todavía participa en la resolución de sobrecarga.
Esta es una nueva característica de C ++ 0x que le dice al compilador que cree la versión predeterminada del constructor u operador de asignación respectivo, es decir, la que solo realiza la acción de copiar o mover para cada miembro. Esto es útil porque el constructor de movimiento no siempre se genera de manera predeterminada (por ejemplo, si tiene un destructor personalizado), a diferencia del constructor de copia (y de la misma manera para la asignación), pero si no hay nada no trivial para escribir, es mejor dejar que el compilador lo maneja que deletrearlo cada vez.
Observe también que no se generaría un constructor predeterminado si proporciona cualquier otro constructor no predeterminado. Si todavía desea el constructor predeterminado, también, puede usar esta sintaxis para que el compilador haga uno.
Como otro caso de uso, hay varias situaciones en las que un constructor de copia no se generaría implícitamente (por ejemplo, si proporciona un constructor de movimiento personalizado). Si aún desea la versión predeterminada, puede solicitarla con esta sintaxis.
Vea la Sección 12.8 de la norma para más detalles.
operator new/new[]
, operator delete/delete[]
y sus sobrecargas.
Es nuevo en C ++ 11, ver aquí . Puede ser bastante útil si ha definido un constructor, pero desea utilizar los valores predeterminados para los demás. Antes de C ++ 11, tendría que definir todos los constructores una vez que haya definido uno, incluso si son equivalentes a los valores predeterminados.
También tenga en cuenta que en ciertas situaciones es imposible proporcionar un constructor predeterminado definido por el usuario que se comporte de la misma manera que el compilador sintetizado bajo la inicialización predeterminada y de valor . default
le permite recuperar ese comportamiento.
C ++ 17 N4659 borrador estándar
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Funciones explícitamente predeterminadas":
1 Una definición de función de la forma:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
se llama una definición explícitamente predeterminada. Una función que está explícitamente predeterminada
(1.1) - ser una función miembro especial,
(1.2): tienen el mismo tipo de función declarada (excepto para posibles calificadores de referencia diferentes y excepto que en el caso de un constructor de copia u operador de asignación de copia, el tipo de parámetro puede ser "referencia a T no constante", donde T es el nombre de la clase de la función miembro) como si se hubiera declarado implícitamente, y
(1.3): no tiene argumentos predeterminados.
2 Una función explícitamente predeterminada que no se define como eliminada puede declararse constexpr solo si se hubiera declarado implícitamente como constexpr. Si una función se omite explícitamente en su primera declaración, se considera implícitamente constexpr si la declaración implícita lo fuera.
3 Si una función que está explícitamente predeterminada se declara con un especificador noexcept que no produce la misma especificación de excepción que la declaración implícita (18.4), entonces
(3.1) - si la función está explícitamente predeterminada en su primera declaración, se define como eliminada;
(3.2) - de lo contrario, el programa está mal formado.
4 [Ejemplo:
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
- ejemplo final]
5 Las funciones predeterminadas explícitamente y las funciones declaradas implícitamente se denominan colectivamente funciones predeterminadas, y la implementación proporcionará definiciones implícitas para ellas (15.1 15.4, 15.8), lo que podría significar definirlas como eliminadas. Una función es proporcionada por el usuario si es declarada por el usuario y no está explícitamente predeterminada o eliminada en su primera declaración. Una función explícitamente predeterminada por el usuario (es decir, explícitamente predeterminada después de su primera declaración) se define en el punto donde está explícitamente predeterminada; si dicha función se define implícitamente como eliminada, el programa está mal formado. [Nota: Declarar una función como predeterminada después de su primera declaración puede proporcionar una ejecución eficiente y una definición concisa al tiempo que permite una interfaz binaria estable a una base de código en evolución. - nota final]
6 [Ejemplo:
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
- ejemplo final]
Entonces, la pregunta es, por supuesto, qué funciones pueden declararse implícitamente y cuándo sucede eso, lo que he explicado en: