2012-12-19 12 views
5

Mögliche Duplizieren:
initializer_list and move semanticsIst es sicher, Elemente einer Initialisierungsliste zu verschieben?

In diesem Code:

#include <vector> 
#include <initializer_list> 

template<typename T> 
class some_custom_container : public std::vector<T> 
{ 
public: 
    some_custom_container(const std::initializer_list<T>& contents) 
    { 
     for (auto& i : contents) 
     this->emplace_back(std::move(i)); 
    } 
}; 

class test_class 
{}; 

int main() 
{ 
    test_class a; 

    some_custom_container<test_class> i = { a, test_class(), a }; 
} 

Wenn ich es habe verstehen, werden alle Objekte in { a, test_class(), a } sind sicher ausgebaute: die named- Objekte werden kopiert und die unbenannten Objekte werden verschoben, um die initializer_list zu erstellen. Danach wird diese initializer_list mit Verweis auf den some_custom_container Konstruktor übergeben.

Um unnötige Doppelkopien zu vermeiden, bewege ich alle, um den Vektor zu füllen.

Ist dieser Konstruktor sicher? Ich meine, in einer seltsamen Situation, zum Beispiel, wenn T als Referenz & oder & & ausgewertet wird, ist der Vektor immer gut gefüllt (enthält es sichere Objekte)?

Wenn dies der Fall ist, warum die initializer_list Konstruktorimplementierungen von STL-Container auf diese Weise nicht implementiert sind? Wie ich weiß, kopieren ihre Konstruktoren den Inhalt und verschieben ihn nicht.

+0

Es wird nicht einmal kompiliert, weil Initialisierungslisten nur const Zugriff auf ihre Inhalte bieten und Sie nicht von Referenzen auf const verschieben können. Siehe auch: http://stackoverflow.com/questions/8468774/can-i-list-initialize-a-vector-of-move-only-type –

+2

Das wird nicht verhindern, dass es kompiliert, nur bewegt. Der Kopierkonstruktor würde aufgerufen werden. – Puppy

Antwort

4

initializer_list bietet nur const Zugriff auf seine Elemente. Sie könnten const_cast verwenden, um diesen Code zu kompilieren, aber dann können die Bewegungen zu undefiniertem Verhalten führen (wenn die Elemente initializer_list wirklich const sind). Also, nein, es ist nicht sicher, das zu bewegen. Dort are workarounds for this, wenn Sie es wirklich brauchen.

+0

Betrachten Sie die in Idiom beschrieben auf cpptruths (http://cpptruths.blogspot.com/2013/09/21-ways-of-passing-parameters-plus-one.html). Die Idee ist, lvalue/rvalue zur Laufzeit zu bestimmen und dann move oder copy-construction aufzurufen. in wird rvalue/lvalue erkennen, obwohl die von initializer_list bereitgestellte Standardschnittstelle const referenz ist. – Sumant

+0

@Sumant Stellt dieses humungous Chaos tatsächlich irgendeinen meßbaren Nutzen zur Leistung oder Gedächtnisnutzung zur Verfügung, und wenn ja, eine genügend große Menge solcher Nutzen, um angemessen auszugleichen, wie schrecklich es aussieht und die Tatsache, dass es ungefähr eine Stunde dauert, um herauszufinden, was es ist versuchen zu tun? Ich bezweifle es irgendwie. –