2016-11-17 2 views
7

Unten ist die minimalistische Problem des Codes:Compilerfehler, wenn destructor in der Klasse Körper mit unique_ptr als Mitglied derselben Klasse deklariert

struct B { 
    B() = default; 
    //~B() {}; // error: use of deleted function ‘B& B::operator=(const B&)’ 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 

Above Code kompiliert gut, es sei denn, die destructor unkommentiert ist. Für meine Anforderung muss ich einen Körper von ~B() explizit definiert haben.

Wie kann ich den Körper des Destruktor mit der unique_ptr Koexistenz in der gleichen Klasse definieren?

Hinweis: Versuchte definieren = default Versionen Kopie & bewegen Konstruktor ohne Erfolg. In meinem echten Code ist unique_ptr<int>unique_ptr<forward_declared_class>. Konnte dieses Problem in SO nicht finden, obwohl ich sicher bin, dass es vorhanden sein muss. Fühlen Sie sich frei, als Dupe zu markieren.

+0

Forward deklariert ist relevant für das Problem - kann 'delete' nicht zuverlässig aufrufen (d. H. Kann' std :: default_deleter' nicht instanziieren) ohne einen sichtbaren Destruktor. – milleniumbug

+0

Siehe diese Frage http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t – milleniumbug

+0

Es gibt keinen Grund, nullptr zu m_pB zuweisen. –

Antwort

5

Scheint, wie der Code für std::vector (zumindest für Visual C++, die ich getestet) B kopieren konstruierbar und kopieren zuweisbare erfordert .

Copy-Konstruktor und kopieren assignement Operatoren nur = delete sein können wegen std::unique_ptr (Implementierungen erklärt = default die Funktion führen sollte auch gelöscht werden) und durch destructor Implementierung Sie Standardimplementierungen von Bewegung Konstruktor deaktivieren und Zuweisungsoperator bewegen.

Sie müssen also den Verschiebungszuweisungsoperator explizit deklarieren. Versuchen Sie:

#include <memory> 
#include <vector> 

struct B { 
    B() = default; 
    ~B() {} 
    B& operator=(B&&) = default; 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
3

Sie könnten einen move-assignment-Operator deklarieren und implementieren, nach dem der Compiler fragt. Natürlich beschwert es sich über Kopieraufträge, aber eine sinnvolle Kopie scheint für Ihre Struktur unmöglich zu sein.

Wahrscheinlich ist die Fehlermeldung ein wenig irreführend, weil die std::vector::erase Implementierung so etwas wie _data[i-1] = _data[i] im Code enthält, der Vektorelemente an Orte gelöschter Elemente stößt. Der Compiler benötigt also einen beliebigen Zuweisungsoperator und wir stellen ihm einen beweglichen Operator zur Verfügung.

Zum Beispiel arbeitet das feine (gcc 4.8.3):

struct B { 
    B() = default; 
    B& operator=(B&& op) { 
    m_pB = std::move(op.m_pB); 
    return *this; 
    } 
    ~B() {}; // no more errors. 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
0

Der Vektorcode ist ein red Hering.

Wenn eine Klasse U ein Member vom Typ unique_ptr hat und T vorwärts deklariert ist, muss die Definition des Destruktors in der cpp-Datei enthalten sein, wenn U nicht länger ein unvollständiger Typ ist.

Sie sollten ~ U() haben; in der Kopfzeile und in der cpp-Datei haben U :: ~ U() {} oder U :: ~ U() = Standard;

Verwandte Themen