Lo que son todos los miembros de las funciones creado por el compilador para una clase? ¿Que sucede todo el tiempo? como destructor.
Mi preocupación es si es creada para todas las clases, y por qué es el constructor por defecto que se necesitan?

InformationsquelleAutor Onnesh | 2010-09-17

5 Comentarios

  1. 84

    C++98/03

    Si son necesarias,

    1. el compilador generará un constructor predeterminado para usted, a menos que declare cualquier constructor de su propio.
    2. el compilador generará un copia constructor para usted, a menos que declare su propia.
    3. el compilador generará un copia operador de asignación para usted, a menos que declare su propia.
    4. el compilador generará un destructor para usted, a menos que declare su propia.

    Como Péter dijo en un comentario útil, todos esos son sólo generado por el compilador cuando son necesarias. (La diferencia es que, cuando el compilador no puede crear ellos, eso está bien siempre y cuando no se usa.)


    C++11

    C++11, añade las siguientes reglas, que también son verdaderos para C++14 (créditos a towi, ver este comentario):

    • El compilador genera el mover constructor si
      • no hay ningún usuario-declaró copia constructor, y
      • no hay ningún usuario-declaró copia operador de asignación, y
      • no hay ningún usuario-declaró mover operador de asignación y
      • no hay ningún usuario-declaró destructor,
      • es no marcado como eliminado,
      • y todos los miembros y las bases son móvil.
    • Similar para el mover operador de asignación: se genera si no es definido por el usuario
      • no hay ningún usuario-declaró copia constructor, y
      • no hay ningún usuario-declaró copia operador de asignación, y
      • no hay ningún usuario-declaró mover constructor y
      • no hay ningún usuario-declaró destructor,
      • es no marcado como eliminado,
      • y todos los miembros y las bases son móvil.

    Tenga en cuenta que estas reglas son un poco más elaborada que la de C++03 reglas y hacer más sentido en la práctica.

    Para una más fácil comprensión de qué es lo que de la anterior aquí los elementos para Thing:

    class Thing {
    public:
        Thing();                        //default constructor
        Thing(const Thing&);            //copy c'tor
        Thing& operator=(const Thing&); //copy-assign
        ~Thing();                       //d'tor
        //C++11:
        Thing(Thing&&);                 //move c'tor
        Thing& operator=(Thing&&);      //move-assign
    };

    Y como lectura adicional, si usted es un C++-principiante considerar un diseño que no requiere que usted para poner en práctica cualquiera de los últimos cinco años, un.k.un La Regla De Cero (por Martinho Fernandes).

    • En aras de la precisión, todos estos se generan sólo cuando son realmente necesarias, no siempre. E. g. operador de asignación se genera sólo si hay una asignación real de tomar lugar a una instancia de la clase en cuestión.
    • Es lo que hace. Las reglas son ligeramente más complejo de lo que yo entiendo, para asegurarse de que C++03 de estilo clases se comportan como se esperaba. Yo no soy un experto en 0x pero entiendo que un movimiento constructor no se genera si la clase tiene un usuario-declaró constructor de copia. Usted puede declarar una = default si desea que la implementación predeterminada uno nuevo.
    • Aunque el impago de las operaciones de movimiento probablemente tendrá involuntaria semántica si el valor predeterminado de las operaciones de copia de hacer lo malo y por lo tanto tenía que ser de forma manual proporcionado.
    • De acuerdo. Sería una extraña situación eran una costumbre constructor de copia se requiere, pero por defecto mover constructor ha funcionado muy bien.
    • Gracias, he incorporado en mi respuesta.
    • Es lo que hace. El compilador genera el Mover C tor si no hay definido por el usuario Copiar C tor, Copiar Asignar, Mover Asignar o Destructor, y no está marcado como eliminado y todos los miembros son móviles. Similares para Mover Asignar: se genera si no es definido por el usuario Copiar C tor, Copiar C tor, Mover Asignar o Destructor, y no está marcado como eliminado y todos los miembros son móviles. Tenga en cuenta que estas reglas son un poco más elaboradas como el C++03 reglas y hacer más sentido en la práctica.
    • Muchas gracias por la excavación de esta respuesta anterior y añadiendo a ella! He intentado cambiar el formato de la respuesta para hacer un poco más uniforme. Por favor, siéntase libre de cambiar esto, de nuevo, si la puse nada en el proceso.
    • «…y todos los miembros y las bases se pueden mover». No debería ser «…y todos los miembros y las bases son los bienes muebles o copiable»?

  2. 2

    Quieres decir con ‘definido’ por ‘creado’?

    $12.1 – «El constructor predeterminado (12.1), constructor de copia y copia operador de asignación (12.8), y el destructor (12.4) son funciones miembro especiales.

    Si ‘creado’ significa ‘definido’, entonces, aquí son las partes importantes del Estándar de C++.

    -Un implícitamente-declaró la cesación de constructor para una clase está implícitamente definido cuando se utiliza para crear un objeto de su clase tipo (1.8).

    -Si una clase no tiene ningún usuario-declaró destructor, un destructor es declarado implícitamente. Un implícitamente-declaró destructor está implícitamente definido cuando se utiliza para destruir un objeto de su clase y tipo.

    -Si la definición de la clase no se declara explícitamente un constructor de copia, uno se declara implícitamente. Un implícitamente-declaró constructor de copia está implícitamente definido si se utiliza para inicializar un objeto de su clase tipo a partir de una copia de un objeto de su clase, de tipo o de un tipo de clase que deriva de su tipo de clase).

    -Si la definición de la clase no declara explícitamente una copia operador de asignación, uno se declara implícitamente. Un implícitamente-declaró copia operador de asignación está implícitamente definido cuando un objeto de su tipo de clase se le asigna un valor de su tipo de clase o un valor de un tipo de clase que deriva de su tipo de clase.

  3. 1

    Por defecto, si no se implementa por el usuario, el compilador añade algunas funciones miembro para la clase. Esos son llamados los cuatro grandes :

    • constructor predeterminado
    • constructor de copia
    • copia operador (de asignación)
    • destructor

    Dependiendo de los tipos de los miembros y que la función de miembro enumerados usted proporcione, aquellos que no se genera.

  4. 0

    Otras respuestas han dicho lo creado, y que el compilador puede generar sólo si se utiliza.

    Mi preocupación es si es creada para todas las clases…

    ¿Por qué preocuparse? El pensamiento es la creación de código no deseado en el ejecutable? Raro, pero se puede comprobar fácilmente con su entorno.

    O, tal vez, su preocupación era que no podría crear un constructor cuando quieres uno? Nada de que preocuparse… siempre están creadas, si es necesario y no proporcionados por el usuario.

    …y ¿por qué es constructor predeterminado que se necesitan?

    Ya que las clases pueden tener los objetos dentro de ellos con sus propios destructores que deben ser sistemáticamente se invoca. Por ejemplo, dado…

    struct X
    {
        std::string a;
        std::string b;
    };

    …el destructor predeterminado se asegura de que los destructores de a y b.

    • No, los destructores de b y a se ejecutará automáticamente después se ejecuta el vacío X destructor.
    • De un usuario-código de punto de vista, la verdadera. Pero el compilador es la concatenación de todos explícito X la destrucción del cuerpo (si está disponible) con la sub-objeto destructores para formar la real función de destructor.
  5. 0

    C++17 N4659 borrador de estándar de

    https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 6.1 «Declaraciones y definiciones» tiene una nota que es muy probable que resume todos ellos:

    3
    [ Nota: En algunas circunstancias, C ++ implementaciones de definir implícitamente el constructor predeterminado (15.1), copia
    constructor (15.8), mover constructor (15.8), copia operador de asignación (15.8), mueva el operador de asignación (15.8),
    o destructor (15.4) funciones miembro. — nota final ] [ Ejemplo: Dado

    #include <string>
    
    struct C {
      std::string s;         //std::string is the standard library class (Clause 24)
    };
    
    int main() {
      C a;
      C b = a;
      b = a;
    }

    la aplicación implícitamente definir las funciones a realizar la definición de C equivalente a

    struct C {
      std::string s;
      C() : s() { }
      C(const C& x): s(x.s) { }
      C(C&& x): s(static_cast<std::string&&>(x.s)) { }
      //: s(std::move(x.s)) { }
      C& operator=(const C& x) { s = x.s; return *this; }
      C& operator=(C&& x) { s = static_cast<std::string&&>(x.s); return *this; }
      //{ s = std::move(x.s); return *this; }
      ~ C() { }
    };

    — end ejemplo ]

    Las condiciones en que estos se declaran se explican en: Condiciones para la generación automática de forma predeterminada/copiar/mover cto r y copiar/mover operador de asignación?

    Una buena manera de asegurarse de que algo tiene un valor por defecto es para probar y hacer uso = default como se explica en: ¿Qué es un «defecto» significa que después de una clase de’ declaración de la función?

    El siguiente ejemplo hace, y también ejerce todas las funciones definidas implícitamente.

    #include <cassert>
    #include <string>
    struct Default {
    int i;
    Default()                          = default;
    Default(const Default&)            = default;
    Default& operator=(Default&)       = default;
    Default& operator=(const Default&) = default;
    Default(Default&&)                 = default;
    Default& operator=(Default&&)      = default;
    ~Default()                         = default;
    };
    struct Instrument {
    int i;
    static std::string last_call;
    Instrument()                             { last_call = "ctor"; }
    Instrument(const Instrument&)            { last_call = "copy ctor"; }
    Instrument& operator=(Instrument&)       { last_call = "copy assign"; return *this; }
    Instrument& operator=(const Instrument&) { last_call = "copy assign const"; return *this; }
    Instrument(Instrument&&)                 { last_call = "move ctor";  }
    Instrument& operator=(Instrument&&)      { last_call = "move assign"; return *this; }
    ~Instrument()                            { last_call = "dtor"; }
    };
    std::string Instrument::last_call;
    int main() {
    //See what the default constructors are doing.
    {
    //Default constructor.
    Default ctor;
    //i is uninitialized.
    //std::cout << ctor.i << std::endl;
    ctor.i = 1;
    //Copy constructor.
    Default copy_ctor(ctor);
    assert(copy_ctor.i = 1);
    //Copy assignment.
    Default copy_assign;
    copy_assign = ctor;
    assert(copy_assign.i = 1);
    //Copy assignment const.
    const Default const_ctor(ctor);
    Default copy_assign_const;
    copy_assign_const = const_ctor;
    assert(copy_assign_const.i == 1);
    //Move constructor.
    Default move_ctor(std::move(ctor));
    assert(move_ctor.i == 1);
    //Move assignment.
    Default move_assign;
    move_assign = std::move(ctor);
    assert(move_assign.i == 1);
    }
    //Check that the constructors are called by these calls.
    {
    //Default constructor.
    Instrument ctor;
    assert(Instrument::last_call == "ctor");
    //Copy constructor.
    Instrument copy_ctor(ctor);
    assert(Instrument::last_call == "copy ctor");
    //Copy assignment.
    copy_ctor = ctor;
    assert(Instrument::last_call == "copy assign");
    //Copy assignment const.
    const Instrument const_ctor(ctor);
    Instrument copy_assign_const;
    copy_assign_const = const_ctor;
    assert(Instrument::last_call == "copy assign const");
    //Move constructor.
    Instrument move_ctor(std::move(ctor));
    assert(Instrument::last_call == "move ctor");
    //Move assignment.
    Instrument move_assign;
    move_assign = std::move(ctor);
    assert(Instrument::last_call == "move assign");
    //Destructor.
    {
    Instrument dtor;
    }
    assert(Instrument::last_call == "dtor");
    }
    }

    GitHub aguas arriba.

    Probado con GCC 7.3.0:

    g++ -std=c++11 implicitly_defined.cpp

Dejar respuesta

Please enter your comment!
Please enter your name here