2016-07-28 7 views
1

Ich habe eine Klasse, die eine const vector Mitglied hat, die eindeutige Zeiger auf einige Objekte enthält. Bei der Konstruktion sollte das sequence-Objekt den Besitz des Vektors eindeutiger Zeiger stehlen, der an den Konstruktor übergeben wird, so dass das Sequenzobjekt jetzt der Besitzer der Objekte ist, die den eindeutigen Zeigern im Vektorparameter gehörten.C++ Embedded Lambda in Initializer-Liste für const Vektor Mitglied

class sequence 
{ 
    const std::vector< std::unique_ptr<statement> > m_statements; 

    sequence(std::vector< std::unique_ptr<statement> > & statements); 
}; 

Das erste Mal, dass ich den Konstruktor umzusetzen versuchte, habe ich folgendes:

sequence::sequence(vector< unique_ptr<statement> > & statements) 
    m_statements(statements) 
{ 
} 

Aber natürlich diese nicht kompiliert, da man eine unique_ptr nicht kopier konstruieren kann und somit‘ t copy-construct a vector.

C++ erlaubt nicht, const Mitglieder im Körper des Konstruktors zu initialisieren (wie Java mit letzten Mitgliedern tut), aber nur innerhalb der Initialisiererliste. Eine mögliche Lösung könnte also sein, den const Modifikator von m_statement zu löschen und den Inhalt mit einer Schleife von einem Vektor zum anderen im Körper des Konstruktors zu verschieben.

Aber ich möchte diesen Modifikator const behalten.

So kam ich zu einer anderen Lösung, die scheint zu kompilieren, aber weil ich neu in C++ 11 bin, bin ich mir nicht sicher, was es genau tut. Die Idee war, die oben beschriebene Schleife in eine Lambda-Funktion einzubetten, so dass ich m_statement innerhalb der Initialisierungsliste unter Verwendung einer Schleife initialisieren konnte und den const Modifizierer weiterhin auf m_statement behalten konnte.

sequence::sequence(vector< unique_ptr< const statement > > & statements) : 
    m_statements(([ & statements ] { 
     vector< unique_ptr< const statement > > copied_vec; 
     for(auto & stm : statements) 
      copied_vec.push_back(move(stm)); 
     return copied_vec; 
    })()) 
{ 
} 

Dies kompiliert. Aber ich bin mir nicht sicher, was passiert, beginnend mit der Rückgabe der Lambda-Funktion.

Ich nehme an, dass eine Kopie von copied_vec gemacht und zurückgegeben wurde. Was passiert, wenn Sie einen Vektor eindeutiger Zeiger nach Wert zurückgeben? Ist es eine richtige Art zu tun, was ich will, obwohl es seltsam ist, oder muss ich einfach den const Modifikator auf m_statetent fallen lassen? Vielen Dank.

+1

beantwortet nicht die Frage auf, wie Ihr Code funktioniert, aber [dies] (http://stackoverflow.com/questions/18282204/proper-way-of-transferring-ownership-of-a-stdvector- stdunique-ptr-int-t) zeigt Ihnen den richtigen Weg zum Verschieben des Vektors. – NathanOliver

+0

Sie erstellen ein Lambda, dann rufen Sie es an. Clever, wenn auch unnötig. – lorro

+0

@NathanOliver Danke. Ich bin sprachlos, um zu sehen, wie einfach es war. – Virus721

Antwort

6

Fehle ich einen Grund, warum ein Move-Konstruktor nicht verwendet werden kann?

sequence::sequence(vector< unique_ptr<statement> > && statements) 
    m_statements(std::move(statements)) 
{ 
} 
+0

Danke für Ihre Hilfe. Daran habe ich einfach nicht gedacht. Trotzdem würde ich gerne wissen, was passiert, wenn ich 'copied_vec' kopiere, indem ich den Rückgabewert verwende. – Virus721

+0

Abhängig von "Details" denke ich, dass Sie wahrscheinlich eine Form von RVO bekommen werden. Ich denke mit C++ 17 ist es sogar vorgeschrieben (wieder abhängig von Details). – KayEss

+0

Danke. Aber was passiert, wenn man einen Vektor eindeutiger Zeiger kopiert, wenn man diese implizite Compiler-Optimierung ignoriert? Der Besitz wird von den Zeigern des Quellenvektors zu den Zeigern des neu erzeugten Vektors verschoben. – Virus721