Kiedy to zrobię:
std::vector<int> hello;
Wszystko działa świetnie. Kiedy jednak zrobię z tego wektor odnośników:
std::vector<int &> hello;
Dostaję straszne błędy jak
błąd C2528: „wskaźnik”: wskaźnik do odwołania jest nielegalny
Chcę umieścić wiele wektorów struktur w wektorze, aby nie musiałem mieszać się ze wskaźnikami. Dlaczego wektor wywołuje w tym napad złości? Czy moją jedyną opcją jest użycie wektora wskaźników?
Odpowiedzi:
Typ komponentów pojemników, takich jak wektory, musi być możliwy do przypisania . Odniesień nie można przypisać (możesz je zainicjować tylko raz, gdy zostaną zadeklarowane, i nie możesz później zmuszać ich do odwoływania się do czegoś innego). Inne typy nieprzenoszalne również nie są dozwolone jako elementy kontenerów, np.
vector<const int>
Nie są dozwolone.źródło
tak, możesz poszukać
std::reference_wrapper
, który naśladuje odniesienie, ale można go przypisać i można go również „zresetowa攟ródło
get()
gdy próbujesz uzyskać dostęp do metody instancji klasy w tym opakowaniu? Np.reference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();
Nie jest bardzo odniesienia..get()
. Czego chce Timdielsoperator.
; spójrz na najnowsze propozycje / dyskusje na ten temat.Ze swej natury odniesienia można ustawiać tylko w momencie ich tworzenia; tj. następujące dwie linie mają bardzo różne efekty:
Ponadto jest to nielegalne:
Jednak podczas tworzenia wektora nie ma możliwości przypisania wartości do jego elementów podczas tworzenia. Zasadniczo robisz całą masę ostatniego przykładu.
źródło
Ion Todirel już wspomniano odpowiedź TAK użyciu
std::reference_wrapper
. Od wersji C ++ 11 mamy mechanizm pobierania obiektustd::vector
i usuwania referencji za pomocąstd::remove_reference
. Poniżej podano przykład skompilowany przy użyciug++
izclang
opcją-std=c++11
i wykonany pomyślnie.źródło
std::remove_reference<>
. Chodzi ostd::remove_reference<>
to, aby pozwolić ci napisać „typ T, ale bez bycia referencją, jeśli tak jest”. Tostd::remove_reference<MyClass&>::type
jest tak samo jak pisanieMyClass
.for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n";
(lubfor (const MyClass& obj3: vec)
jeśli zadeklarujeszgetval()
const, tak jak powinieneś).boost::ptr_vector<int>
będzie działać.Edycja: była sugestią użycia
std::vector< boost::ref<int> >
, która nie będzie działać, ponieważ nie można domyślnie skonstruować plikuboost::ref
.źródło
resize
.Jest to usterka w języku C ++. Nie możesz pobrać adresu referencji, ponieważ próba zrobienia tego spowodowałaby adres obiektu, do którego się odnosi, a zatem nigdy nie możesz uzyskać wskaźnika do referencji.
std::vector
współpracuje ze wskaźnikami do jego elementów, więc przechowywane wartości muszą być możliwe do wskazania. Zamiast tego będziesz musiał użyć wskaźników.źródło
sizeof
odniesienia.TL; DR
Użyj w
std::reference_wrapper
ten sposób:Demo
Długa odpowiedź
Jako standard ten sugeruje , dla standardowego kontenera
X
zawierającego obiekty typuT
,T
może byćErasable
zX
.Erasable
oznacza, że następujące wyrażenie jest dobrze uformowane:A
jest typem alokatora kontenera,m
jest instancją alokatora ip
jest wskaźnikiem typu*T
. Patrz tutaj dlaErasable
definicji.Domyślnie
std::allocator<T>
jest używany jako alokator wektora. W domyślnym alokatorze wymaganie jest równoważne z ważnościąp->~T()
(Uwaga:T
jest to typ odwołania ip
jest wskaźnikiem do odwołania). Jednak wskaźnik do odwołania jest nielegalny , dlatego wyrażenie nie jest dobrze uformowane.źródło
Jak już wspomnieli inni, prawdopodobnie zamiast tego użyjesz wektora wskaźników.
Możesz jednak rozważyć użycie ptr_vector !
źródło
Jak sugerują inne komentarze, ograniczasz się do używania wskaźników. Ale jeśli to pomaga, oto jedna technika, aby uniknąć bezpośredniego spojrzenia na wskaźniki.
Możesz zrobić coś takiego:
źródło
reinterpret_cast
nie jest potrzebny