2015-03-29 15 views
6

Ich habe eine class A mit einer Elementvariable _atomicVar des Typs std::atomic<int>.
Fehler C2280: versucht, eine gelöschte Funktion (atomare <int>)

#include <atomic> 

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

private: 
    std::atomic<int> _atomicVar; 
}; 

Wenn ich das Projekt, das ich die folgende Fehlermeldung erhalten bauen:

error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)' : attempting to reference a deleted function 

Ich bin in erster Linie ein C# -Entwickler, so weiß ich nicht jedes Detail von C++ (noch) nicht. Ich weiß nicht, wo ich die Kopie c'tor von atomic<int> verwende.
Ich habe auch versucht _atomicVar zu initialisieren:

std::atomic<int> _atomicVar { 0 }; 

... aber das hat nicht funktioniert.
Ich würde erwarten, dass _atomicVar (ohne eine explizite Initialisierung) mit dem Standardwert für int initialisiert werden würde.
Können Sie mir sagen, warum dieser Fehler auftritt?

+0

Sie scheinen Visual Studio zu verwenden. Welche Version? Auch auf welcher Codezeile erhalten Sie den Fehler? –

+2

Ist es Ihr gesamter Code? Vielleicht kopierst du 'A' Objekte? Vielleicht verwenden Sie einen Container, der 'CopyConstructible' Elemente benötigt? – zch

+2

Einfach den Kopierkonstruktor nicht zu definieren ist genug Grund dafür.Wenn Sie Typen definieren, die atomare Elemente enthalten, müssen Sie explizit gültige Semantik für alle impliziten Operationen definieren, die vom Compiler ausgeführt oder eingefügt werden können. –

Antwort

14

Das ist, weil Kopie Konstruktor von std::atomic ist gelöscht.

Siehe this documentation page.

Da Sie keinen expliziten Kopierkonstruktor für A definieren, generiert der Compiler den Standardwert one, der einfach Kopierkonstruktoren für alle Member aufruft (was für std::atomic nicht zulässig ist).

Lösung:

class A 
{ 
public: 
    A(); 
    A(const A& origin); // add this line 
    ~A(); 
private: 
    std::atomic<int> _atomicVar; 
}; 

A::A(const A& origin) 
: _atomicVar(0) //zero-initialize _atomicVar 
{ 
} 

EDIT

Wenn Sie sich fragen, warum atomic Typen nicht kopierbar sind, möchten Sie vielleicht this question, vor allem akzeptierte Antwort lesen. Wenn Sie Wert von std::atomic kopieren möchten, können Sie es tun:

A::A(const A& origin) 
: _atomicVar(origin._atomicVar.load()) 
{ 
} 

Aber bedenken Sie, dass dieser Vorgang selbst wird nicht ein Atom sein (und für die meisten Logiken, bedeutungslos).

Sie können auch explizite Zuweisungsoperator definieren (erinnern Sie sich an Rule of Three).

Die beste Option für das richtige Verhalten Ihres Programms würden diese beiden Methoden werden zu löschen:

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

    A& operator=(const A&) = delete; 

private: 
    std::atomic<int> _atomicVar; 
}; 

Wenn Ihr Compiler dies nicht unterstützt (zB jede VC vor VC12), sie als privat deklariert und nicht Stellen Sie einen Körper:

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

private: 
    //do not define these two 
    A(const A&); 
    A& operator=(const A&); 

private: 
    std::atomic<int> _atomicVar; 
}; 
+3

Ehm, ich würde das nicht machen - jetzt ist 'A's Kopiensemantik kaputt. Ich würde stattdessen 'A's Kopierkonstruktor löschen. –

+1

Ja, du hast Recht. Ich habe meine Antwort bereits aktualisiert, als du das geschrieben hast. –

+0

Vielen Dank @MateuszGrzejek das hat mir wirklich geholfen, ich habe eine Klasse, die mit einem shared_ptr instanziiert wurde, und die Klasse selbst hielt eine unique_ptr für eine Forward-Deklaration, ich verstand nicht den Fehler, den ich bekam, seit ich einen Standard bereitgestellt hatte Destruktor benötigt eine Forward-Deklaration in einem unique_ptr, nachdem ich dies gelesen und einen zusätzlichen Copy-Konstruktor in der Klasse erstellt habe, um unique_ptr nullptr zu setzen, bis der rechte Konstruktor aufgerufen wurde, mein Code funktioniert, also danke für eine gute Antwort, half (= – daniel

Verwandte Themen