Pregunta

Sé que si sale de un miembro de una lista de inicialización en un constructor sin argumentos, el constructor por defecto de ese miembro será llamado.

Haz constructores de copia asimismo llamar al constructor copia de los miembros, o ellos también llaman el constructor por defecto?

class myClass {
  private:
    someClass a;
    someOtherClass b;
  public:
    myClass() : a(DEFAULT_A) {} //implied is b()
    myClass(const myClass& mc) : a(mc.a) {} //implied is b(mc.b)??? or is it b()?
}
¿Fue útil?

Solución

constructores de copia definido explícitamente no llaman constructores de copia para los miembros.

Al entrar en el cuerpo de un constructor, todos los miembros de esa clase se inicializará. Es decir, una vez que llegue a { se le garantiza que todos sus miembros se han inicializado.

A menos que se especifique, los miembros están en el orden en que aparecen en la clase. Inicializado por defecto (Y si no puede ser, está mal formado el programa.) Así que si usted define su propia constructor de copia, ahora depende de usted para llamar a cualquier miembro de constructores de copia si lo deseas.

Aquí es un pequeño programa que puede copiar y pegar en algún lugar y perder el tiempo con:

#include <iostream>

class Foo {
public:
    Foo() {
        std::cout << "In Foo::Foo()" << std::endl;
    }

    Foo(const Foo& rhs) {
        std::cout << "In Foo::Foo(const Foo&)" << std::endl;
    }
};

class Bar {
public:
    Bar() {
        std::cout << "In Bar::Bar()" << std::endl;
    }

    Bar(const Bar& rhs) {
        std::cout << "In Bar::Bar(const Bar&)" << std::endl;
    }
};

class Baz {
public:
    Foo foo;
    Bar bar;

    Baz() {
        std::cout << "In Baz::Baz()" << std::endl;
    }

    Baz(const Baz& rhs) {
        std::cout << "In Baz::Baz(const Baz&)" << std::endl;
    }
};

int main() {
    Baz baz1;
    std::cout << "Copying..." << std::endl;
    Baz baz2(baz1);
}

y como es, esta impresiones:

In Foo::Foo()
In Bar::Bar()
In Baz::Baz()
Copying...
In Foo::Foo()
In Bar::Bar()
In Baz::Baz(const Baz&)

Tenga en cuenta que se default-inicialización de los miembros de Baz.

Por comentando el constructor copia explícita, como:

/*
Baz(const Baz& rhs) {
    std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
*/

La salida será el siguiente:

In Foo::Foo()
In Bar::Bar()
In Baz::Baz()
Copying...
In Foo::Foo(const Foo&)
In Bar::Bar(const Bar&)

Se llama al constructor de copia en ambos.

Y si reintroducimos constructor de copia de Baz y copia explícitamente un solo miembro:

Baz(const Baz& rhs) :
    foo(rhs.foo)
{
    std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}

Obtenemos:

In Foo::Foo()
In Bar::Bar()
In Baz::Baz()
Copying...
In Foo::Foo(const Foo&)
In Bar::Bar()
In Baz::Baz(const Baz&)

Como se puede ver, una vez que se declara explícitamente un constructor de copia son responsables de la copia de todos los miembros de la clase; es su constructor ahora.

Esto es válido para todos los constructores, incluyendo constructores de movimiento.

Otros consejos

Sí. Ctors son ctors.

Para cualquier variable miembro que tiene un constructor por defecto que se invoca constructor por defecto si no se ha añadido de forma explícita cualquier otra llamada de constructor para que la variable miembro en la lista de inicialización.

Para más detalles ver: ¿Hay un defecto implícita constructor en C ++?

corta:

  • Compilador generada "por defecto Constructor": utiliza el constructor por defecto de cada miembro
  • .
  • Compilador generado "constructor de copia": utiliza el constructor copia de cada miembro.
  • Compiler generada "operador de asignación": utiliza el operador de asignación de cada miembro
  • .

No hay nada mágico sobre un constructor de copia, aparte de que el compilador lo añadirá en caso necesario. Sin embargo, en la forma en que funciona realmente, no hay nada especial -. Si usted no dice explícitamente "utiliza tal y como un constructor", que va a utilizar el valor por defecto

No en VC9. No estoy seguro sobre los otros.

// compiled as: cl /EHsc contest.cpp
//
//    Output was:
//    Child1()
//    -----
//    Child1()
//    Child2()
//    Parent()
//    -----
//    Child1(Child1&)
//    Child2()
//    Parent(Parent&)

#include <cstdio>

class Child1 {
    int x;
public:
    static Child1 DEFAULT;

    Child1(){
        x = 0;
        printf("Child1()\n");
    }

    Child1(Child1 &other){
        x = other.x;
        printf("Child1(Child1&)\n");
    }
};

Child1 Child1::DEFAULT;

class Child2 {
    int x;
public:
    Child2(){
        x = 0;
        printf("Child2()\n");
    }

    Child2(Child2 &other){
        x = other.x;
        printf("Child2(Child2&)\n");
    }
};

class Parent {
    int x;
    Child1 c1;
    Child2 c2;

public:
    Parent(){
        printf("Parent()\n");
    }

    Parent(Parent &other) : c1(Child1::DEFAULT) {
        printf("Parent(Parent&)\n");
    }
};

int main(){
    printf("-----\n");
    Parent p1;
    printf("-----\n");
    Parent p2(p1);

    return 0;
}

En función de cómo se inicia el constructor de llamadas de base, los constructores de los miembros serán llamados de la misma manera. Por ejemplo, vamos a empezar con:

struct ABC{
    int a;
    ABC() : a(0)    {   printf("Default Constructor Called %d\n", a);   };

    ABC(ABC  & other )  
    {
        a=other.a;
        printf("Copy constructor Called %d \n" , a ) ;
    };
};

struct ABCDaddy{
    ABC abcchild;
};

Puede hacer las siguientes pruebas:

printf("\n\nTest two, where ABC is a member of another structure\n" );
ABCDaddy aD;
aD.abcchild.a=2;

printf( "\n Test: ABCDaddy bD=aD;  \n" );
ABCDaddy bD=aD; // Does call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is  called)

printf( "\n Test: ABCDaddy cD(aD); \n" );
ABCDaddy cD(aD);    // Does call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is  called)

printf( "\n Test: ABCDaddy eD; eD=aD;  \n" );
ABCDaddy eD;
eD=aD;          // Does NOT call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is not called)

Salida:

Default Constructor Called 0

Test: ABCDaddy bD=aD;
Copy constructor Called 2

Test: ABCDaddy cD(aD);
Copy constructor Called 2

Test: ABCDaddy eD; eD=aD;
Default Constructor Called 0

Disfrute.

Cuando el compilador proporciona la cctor defecto, ¿qué te parece el compilador hace para las variables miembro? Es copia construcciones a él.

En el mismo sentido, si el cctor es definida por el usuario, y si uno deja fuera a algunos de los miembros, los miembros que no se puede dejar sin inicializar. invariantes clases se establecen durante la construcción y tienen que ser mantenidos constantemente. Por lo tanto, el compilador lo hace por usted.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top