struct A
{
A(const A& arg) : data(arg.data)
{
do_something_special();
}
// by writing copy constructor, we suppress the generation of
// implicit default constructor A::A()
int data;
};
void foo1()
{
A a; // does not work, since there's no default constructor
}
Digamos que nuestro constructor por defecto no hace nada especial y es (más o menos) igual al compilador generó uno. Podemos solucionarlo, ya sea escribiendo nuestro propio constructor por defecto (que puede resultar tedioso si nuestra clase tiene muchos miembros no estáticos), o mediante el uso de la sintaxis = default
:
struct A
{
A() = default;
A(const A& arg) : data(arg.data)
{
do_something_special();
}
int data;
};
Eliminación de funciones es útil cuando quiero prohibir el uso de sobrecargas específicas o especializaciones de plantillas, o simplemente prohibir copiar (o mover) objetos.
void foo(char c) {}
void foo(int i) = delete; // do not allow implicit int -> char conversion
Cuando se quiere prohibir la copia (es decir, objetos de hilo), la forma idiomática habitual es declarar constructor de copia privada sin aplicación (sí, o impulsar el uso :: noncopyable). Si bien esto funciona en la mayoría de los casos, a veces puede entrar en algunos errores oscuros del enlazador. Consideremos:
struct A
{
A() = default;
friend void foo();
private:
A(const A&);
};
void foo()
{
A a;
A b(a); // results in linker error in gcc
}
Haciendo A(const A&)
borrar, le evitan posibles errores de enlace y crea nuestra intención (no permitir la copia) muy claro.
@Christian: Si simplemente teníamos 'struct S {S (int) {}}; ', la presencia de' S (int) 'haría suprimir el constructor predeterminado declarado implícitamente. –
Las reglas para POD se han relajado en C++ 0x/11, por lo que su segundo ejemplo también sería un POD en C++ 0x/11. También puede usar los nuevos rasgos :: is_pod para verificarse con una afirmación estática, por ejemplo. –
David
@David: Las reglas para POD han sido relajadas, pero el segundo 'S' todavía no es POD. Una estructura POD debe ser una clase trivial. Una clase trivial debe tener un constructor predeterminado trivial. Un constructor predeterminado proporcionado por el usuario no es trivial. El segundo 'S' tiene un constructor predeterminado proporcionado por el usuario y, por lo tanto, no es POD. –