2011-11-20 34 views
12

Czy posiadanie wektora odniesień do obiektów jest zgodne z prawem?Wektory odniesień do obiektów

vector<Agent&> seenAgents; 

Który na przykład zostanie wypełniony przez niektóre, ale nie wszystkie obiekty na scenie?

Mam wektor obiektów Agent, ale wektor opisany powyżej powinien zawierać odniesienia tylko do tych, które każdy agent może obecnie zobaczyć - co oznacza, że ​​odniesienia będą dodawane i usuwane przez cały czas.

Czy jest to coś, na co pozwala język? I czy jest jeszcze coś, o czym muszę wiedzieć? Jeśli usunę odniesienie z wektora, czy będzie on trwał w dowolnym miejscu? Czy to przeciek pamięci?

I wydają się być uzyskiwanie ten błąd na linii uznającej Vector:

error C2528: 'pointer' : pointer to reference is illegal 

jest to coś bezpośrednio do czynienia z linii, czy jest to najprawdopodobniej występującego gdzieś indziej? To jest zainicjowany w konstruktorów initialiser listy tak:

seenAgents(vector<Agents&>()) 
+0

Duplikat http://stackoverflow.com/questions/922360/why-cant-i-make-a-vector-of-references –

Odpowiedz

19

Nie można mieć vector referencji, jako odniesienie nie jest copyable cesji i wszystkie kontenery STL mają przechowywać copyable przypisywane przedmiotów.

Ale możesz sprawić, że kontener będzie trzymał wskaźniki. W ten sposób:

vector< Agents* > seenAgents; 

To jest trochę niebezpieczne. Musisz mieć pewność, że te wskaźniki pozostaną ważne. Mam na myśli - jeśli ktoś usunie obiekt, wskazany przez wskaźnik w tym kontenerze, wskaźnik stanie się nieważny. Musisz być pewien, że tak się nie stanie, ponieważ nie możesz go sprawdzić (nie możesz sprawdzić, czy nie ma NULL, ponieważ wskaźnik nie stanie się NULL, jeśli ktoś usunie wskazany obiekt).

Najlepszym rozwiązaniem w tym przypadku (dostarczanym przez kontener ze wskaźnikami) byłoby użycie inteligentnych wskaźników - niektóre z licznikiem referencji, na przykład; zagwarantują ci, że obiekt będzie istnieć i wskaźnik będzie ważny. A w przypadku, gdy obiekt wskazany przez inteligentny wskaźnik zostanie zniszczony, można go sprawdzić pod kątem NULL.

+2

Czy na pewno nie można kopiować referencji? Myślałem, że nie można ich przypisać. – UncleBens

+0

Dobrze, dzięki. Ale nadal nie można "skopiować" odniesienia, ponieważ nie jest to prawdziwy typ, tak naprawdę nie istnieje, mam na myśli - żadna momory nie jest przydzielona do niego (w większości implementacji kompilatora, całkiem pewna - wszystkie z nich). Ale nadal - tak, "przypisywalne" brzmi bardziej poprawnie i mniej dezorientująco. Edytowane :) –

+0

Nie można również domyślnie ich konstruować. –

8

Nie możesz tego zrobić. Użyj wskaźników.

Biblioteka Boost zapewnia PTR_VECTOR który jest lepszym rozwiązaniem niż:

vector<T*> foo; 
+2

Dlaczego 'ptr_vector' jest lepszy niż' wektor '. Kiedy mówisz, że coś jest lepsze, to coś innego opisuje twój wskaźnik. – tomas789

+1

Istnieje wiele powodów, dla których 'ptr_vector's są lepsze, możesz [przeczytać o tym tutaj] (http://www.boost.org/doc/libs/1_55_0/libs/ptr_container/doc/examples.html). Ale w skrócie działają one bardziej jak wektor odniesień i dlatego są generalnie bezpieczniejsze w użyciu. Na przykład nie usuwasz samych wskaźników i nie możesz zapisać wskaźnika "NULL" w wektorze. – edam

+1

Ooops, chciałem powiedzieć "nie można zapisać wskaźnika" NULL "w wektorze" * domyślnie *! – edam

2

chciałem podobną funkcjonalność. W końcu, oto co zrobiłem:

template <class T> class VectorOfRefs : public std::vector<T *> { 
public: 
    inline T & at(const uint64_t i) { 
     T * x = std::vector<T *>::at(i); 
     return *x; 
    } 
}; 

VectorOfRefs <MyType> myVector; 
myVector.push_back(&myInstance0); 
myVector.push_back(&myInstance1); 

// later in the code: 
myVector.at(i).myMethod(); 

Oczywiście jest to wektor wskaźników pod spodem.

Normalnie używam STL i zadowolić myVector.at(i)->myMethod(), ale chciałem użyć operatora ++, więc miałem dwa następujące opcje:

// using STL: 
(*myVector.at(i))++; 

// or, using my wrapper: 
myVector.at(i)++; 

znajdę notacji z owijki daleko korzystnego pod względem czytelności kodu. Nie podoba mi się opakowanie, per se, ale wypłaca dywidendy później.