10

Dies ist nur eine kurze Frage richtig zu verstehen, was passiert, wenn man eine Klasse mit einem Konstruktor wie folgt zu erstellen:Compiler erzeugt Konstrukteurs

class A 
{ 
    public: 
    A() {} 
}; 

Ich weiß, dass kein Standard-Konstruktor erzeugt wird, da er bereits definiert ist, aber Kopier- und Zuweisungskonstruktoren, die vom Compiler generiert wurden, oder mit anderen Worten, muss ich einen privaten Kopierkonstruktor und einen privaten Zuweisungsoperator deklarieren, um dies zu verhindern?

class A 
{ 
    private: 
    // needed to prevent automatic generation? 
    A(const A&); 
    A& operator=(const A&); 
    public: 
    A() {} 
}; 

Antwort

10

Ja. Der Kopierkonstruktor, der Zuweisungsoperator und der Destruktor werden immer unabhängig von anderen Konstruktoren und Operatoren erstellt.

Wenn Sie einen deaktivieren möchten, ist das, was Sie dort haben, perfekt. Es ist auch ziemlich üblich.

+0

der Tat, obwohl, wenn Sie diese verwenden Kopieren/Zuordnung zu verhindern, Check-out [boost :: noncopyable] (http: // www .boost.org/doc/libs/1_55_0/libs/Dienstprogramm/Dienstprogramm.htm # Class_noncopyable). (Sie können diese einfache Klasse ausreißen oder Ihre eigene schreiben und sie wiederverwenden, wo immer Sie wollen.) – TypeIA

13

Ja, Kopieroperatoren für Konstruktoren und Kopien werden auch dann erstellt, wenn Sie einen eigenen Standardkonstruktor deklarieren.

Die Erstellung dieser wird nur unterdrückt, wenn Sie in der Klassendefinition jeweils einen eigenen Kopierkonstruktor oder Kopierzuweisungsoperator deklarieren.

Beachten Sie, dass es möglich ist, sowohl Ihre eigene Kopie Konstruktor zu haben, und einen Compiler einer zur Verfügung gestellt:

struct A { 
    A() { } 
    A(A const&, int foo); 
}; // compiler declares a copy constructor now 

// make the second parameter have a default argument 
// now this constructor is a copy constructor too. 
inline A::A(A const&, int foo = 0) { 

} 

int main() { 
    A a; 
    A b = a; // ambiguity between compiler's one and our custom one! 
} 

The Standard erlaubt jedoch Compiler den Code zu akzeptieren - aber die Wirkung ist ähnlich undefiniertes Verhalten aufweist: Das Programm ist schlecht formatiert, aber für dieses Programm ist keine Warnung/Fehler erforderlich. (frühe GCC-Versionen lehnen diesen Code nicht ab, die jüngsten lehnen ihn ab).

+1

Ihre Beiträge sind "wie üblich" sehr informativ :) –

2

Wenn Sie das Kopieren und Zuweisen deaktivieren möchten, ist es möglicherweise besser, von einer Klasse zu erben, die einen privaten Kopierkonstruktor und Zuweisungsoperator hat (boost::noncopyable ist ein vorgefertigter).

1) Weniger wiederholte Eingabe.

2) Selbstdokumentieren (hoffentlich).

3) Stärker überprüft, dass diese Operationen nicht aufgerufen werden können (weder die Klasse selbst noch die Freunde können Kopien erstellen - dies würde zu einem Compiler und nicht zu einem Linker-Fehler führen).

4) Wird nicht den Standardkonstruktor verstecken :)

#include <boost/noncopyable.hpp> 

class X : boost::noncopyable 
{ 
}; 

int main() 
{ 
    X a, b;  //has default constructor 
    //X c(a); //but can't be copied 
    //a = b; //or assigned 
}