2012-10-16 9 views
5

Ich möchte eine Liste von Objekten in einem std::vector speichern, aber die Objekte enthalten eine Referenz und können nicht zugewiesen werden. Ich kann das Objekt jedoch kopieren. Die einzige Option, die ich mir vorstellen kann, ist die Verwendung von Zeigern, um die Objekte zu umbrechen und die Zeiger neu zu setzen, wenn sie zugewiesen werden müssen, aber die Syntax würde die Lesbarkeit erheblich reduzieren, besonders wenn Iteratoren verwendet werden Alternative.C++ Verwendung von nicht zuweisbaren Objekten in Vektor

funktioniert nicht:

std::vector<MyObject> myVector; 
//fill the vector 
//... 
myVector[1] = object1; 

Intelligente Zeiger Opfer Lesbarkeit:

std::vector<std::unique_ptr<MyObject>> ptrVector; 
//fill the vector 
//... 
ptrVector[1] = std::unique_ptr<MyObject>(new MyObject(object1)); 

es andere Methoden unassignable Objekte in einem std::vector zu benutzen?

+0

C 11 ++ Unter der Annahme, würde mit 'std :: reference_wrapper' anstelle von herkömmlichen Referenzen eine Lösung sein? – jogojapan

+0

Ich glaube nicht, dass Sie die 'std :: move' in der letzten Codezeile benötigen, da' std :: unique_ptr (...) 'ein rvalue ist. –

+0

@ DavidRodríguez-dribeas Oh ja, das in der Frage behoben. –

Antwort

2

Dies ist keine direkte Antwort auf Ihre Frage, da ich keinen Ersatz für std::vector bieten kann, oder eine andere Art der Verwendung, die es Ihnen erlaubt zu tun, was Sie brauchen.

Wenn es jedoch möglich ist, die Definition von MyObject zu ändern, kann es eine Option sein, es so zu ändern, dass es std::reference_wrapper anstelle von konventionellen Referenzen verwendet. Das würde ermöglichen, dass MyObject zuweisbar ist.

Beispiel:

#include <vector> 
#include <functional> 
#include <iostream> 

struct MyObject 
{ 
    //int &_i; 
    std::reference_wrapper<int> _i; 
    MyObject(int &i):_i(i) {} 
}; 


int main() { 
    std::vector<MyObject> vec; 
    int i1 = 3; 
    int i2 = 4; 
    MyObject c1(i1); 
    MyObject c2(i2); 

    /* Storing object. */ 
    vec.push_back(c1); 

    /* Assigning to it. */ 
    vec[0] = c2; 

    /* Confirming that it's the correct object now. */ 
    for (const MyObject &it : vec) 
    std::cout << it._i << std::endl; 

    /* Modifying the value of its internal reference. */ 
    vec[0]._i.get() = 5; 
    /* Confirming that the original int changed value indeed. */ 
    std::cout << "i2 == " << i2 << std::endl; 

    return 0; 
} 

Caveat: Bestehende Code bereits direkte Zuordnung zu dem Referenzelement enthalten kann (das heißt das Element genannt _i im Code oben). Diese Zuordnungen sollten den Wert des Objekts, auf das sich die Referenz bezieht, ändern. Beim Ersetzen der Referenz durch std::reference_wrapper müssen alle direkten Zuweisungen _i = x durch _i.get() = x ersetzt werden, da sonst die Semantik des Programms komplett geändert wird.

(EDIT) Wenn die verwendeten Referenzen Const-Referenzen const T& sind, kann eine std::reference_wrapper<const T> verwendet werden. Im obigen Beispiel ist die Definition von MyObject ändert sich dann so aus:

struct MyObject 
{ 
    std::reference_wrapper<const int> _i; 
    MyObject(const int &i):_i(i) {} 
}; 
+0

Ich habe gerade festgestellt, dass das Objekt eine 'const'-Referenz enthält, daher hilft das Ändern der Verweise auf Wrapper hier nicht. Ich habe meine Frage bearbeitet, um die Änderung widerzuspiegeln. –

+0

Sie können einen 'std :: reference_wrapper ' (und ersetzen Sie 'int' mit dem Typ, den Sie verwenden) in diesem Fall verwenden. – jogojapan

+0

Oh, haha, als ich das getestet habe, habe ich eine 'const std :: reference_wrapper ' verwendet. Ich habe die Frage rückgängig gemacht. Danke für deine Hilfe! –

0

Warum nicht "MyObject" zuweisbar machen? Sie können den Operator "=" überschreiben, damit "myVector [1] = object1" funktioniert.

+1

Weil 'MyObject' eine Referenz als Mitglied enthält. – jogojapan

Verwandte Themen