2013-07-04 14 views
21

Ist die folgenden genug (aus einer Perspektive, Best-Practice) für einen unbeweglichen Typen?Ist es genug Operator zu löschen = (Typ Typ)?

class A 
{ 
    A(const A&) = delete; 
    A(A&&) = delete; 
    A& operator=(A) = delete; 
public: 
    A(); 
}; 

Oder muss ich separat die kopieren/verschieben Zuweisungsoperatoren löschen? Ist hier auch ein Destruktor erforderlich?

+1

Der Operator, den Sie löschen möchten, ist 'A & operator = (const A &)', ich glaube – porges

+1

@Porges: Nein, ich möchte sowohl 'A & operator = (const A &) '** und **' löschen A & operator = (A &&) '. – ronag

Antwort

8

Ja, die Copykonstruktor deklarieren und kopieren Zuweisungsoperatoren wie deleted genug ist. Da Sie eine Kopie Konstruktor deklarieren und kopieren Zuweisungsoperator der Umzug Konstruktor und Umzug wird Zuweisungsoperator nicht automatisch generiert werden. Sie müssen sie nicht explizit deklarieren .

Von §12.8/9 (Hervorhebung hinzugefügt)

Wenn die Definition einer Klasse X einen Umzug Konstruktor nicht explizit deklariert, wird man implizit als , wenn und nur wenn
vorbelegt deklariert werden - X nicht über einen benutzer erklärt Copykonstruktor,
- X nicht eine vom Benutzer angegebene Unternehmer Kopie Zuordnung hat,
- X nicht über eine benutzer erklärt Bewegung Zuweisungsoperator,
- X keinen Benutzer hat deklarierter Destruktor, und
- der Umzug Konstruktor nicht implizit definiert werden gelöscht.

Von §12.8/20 (Hervorhebung hinzugefügt)

Wenn die Definition einer Klasse X nicht explizit einen Zug Zuweisungsoperator erklärt, wird ein implizit als ausgefallen erklärt, wenn und nur wenn
- X nicht ein benutzer erklärt Copykonstruktor hat,
- X keinen Benutzer deklarierte Bewegung Konstruktor hat,
- X nicht eine vom Benutzer angegebene Unternehmer Kopie Zuordnung hat,
- kein benutzer erklärt destructor haben X und
- der Umzug Zuweisungsoperator nicht implizit definiert als gelöscht würden.

+1

Ist dies mit den neuesten Regeln dafür? Ich erinnere mich, dass es während der Standardisierung viele Diskussionen und Änderungen dieser Regeln gegeben hat. – ronag

+1

Der obige Text stammt aus dem C++ 11 Standard (ISO 14882-2012). Es ist ein C++ 14 Vorschlag ([N3578 - Die Rule of Five "] (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3578.pdf)), die Macht Wenn das, was Sie denken. genehmigt werden Sie auch den Kopierkonstruktor oder kopieren Zuweisungsoperator aus Ihrem Beispiel entfernen _either_ und die gleichen wie erklären sie beide gelöscht beeinflussen bekommen. –

3

Nach [class.copy]/17 operator=(A) ist ein gültiger Kopie Zuweisungsoperator, also ja, es reicht aus, um gelöscht erklärt den impliziten Bewegung Zuweisungsoperator zu unterdrücken und somit zusammen mit dem Copykonstruktor gelöscht wird die Klasse machen nicht kopierbar und nicht bewegbar.

Ihre Klasse ist komplizierter als nötig aber alles, was Sie brauchen, ist:

class A 
{ 
    A(const A&) = delete; 
    A& operator=(A) = delete; 
public: 
    A(); 
}; 

Der Benutzer erklärte Copykonstruktor das implizite bewegen Konstruktor unterdrückt, und der Benutzer deklarierte Kopie Zuweisungsoperator unterdrückt die implizite Bewegung Zuordnung Operator.

Allerdings ist die operator=(A) Form un-idiomatisch, also würde ich dazu neigen, operator=(const A&) = delete sowieso zu verwenden. Es hat den gleichen Effekt.

N.B. Es gibt keinen Grund, gelöschte Funktionen als privat zu deklarieren, und tatsächlich führt dies zu einer viel schlechteren Diagnose. Öffentlich und gelöscht funktioniert meiner Erfahrung nach besser.

Auch ist ein destructor hier erforderlich?

für das, was erforderlich? Es hängt davon ab, was Ihr Standardkonstruktor tut.

+0

Vielleicht wäre es eine gute Idee, um einen Benutzer haben definiert destructor, nur zu respektieren, die [Rule of Three] (https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29) (oder fünf), wenn es keinen anderen Grund. –

+2

I don‘ t denkt 'operator = (A)' besonders unidiomatic ist mehr. es wird ausführlich im Gefolge (und sogar vor!) C++ 11 unterstützt Compiler befürwortet. natürlich macht es keinen Unterschied machen, * in diesem Fall * wo es nur gelöscht -. aber wenn es * * Implementierung würde ich neigt dazu, im ganzen mit dem neuen Idiom beraten –

+0

@KonradRudolph, bei der Deklaration eines Kopiere den Zuweisungsoperator rein zu dem Zweck, ihn zu löschen. Ich würde 'operator = (const A &)' für die Symmetrie und Konsistenz mit dem Kopierkonstruktor verwenden, wenn nichts anderes. 'A (A)' ist offensichtlich kein gültiger Kopierkonstruktor. –

Verwandte Themen