Wymagania dotyczące kontenerów zostały zmienione z C ++ 03 na C ++ 11. Podczas gdy C ++ 03 miał ogólne wymagania (np. Kopiowalność konstruowalności i przypisywalność dla wektora), C ++ 11 definiuje szczegółowe wymagania dotyczące każdej operacji kontenera (sekcja 23.2).
W rezultacie możesz np. Przechowywać w wektorze typ, który można kopiować, ale nie można go przypisać - na przykład strukturę ze stałym składnikiem - o ile wykonujesz tylko określone operacje, które nie wymagają przypisania (konstrukcja i push_back
są takimi operacjami ; insert
nie).
Zastanawiam się: czy to oznacza, że teraz pozwala na to standard vector<const T>
? Nie widzę żadnego powodu, dla którego nie powinien - const T
podobnie jak struktura ze składową stałą jest typem, który można kopiować, ale nie można go przypisać - ale być może coś przeoczyłem.
(Część tego, co sprawia, że myślę, że mogłem coś przeoczyć, jest to, że bagażnik gcc ulega awarii i pali się, jeśli próbujesz utworzyć instancję vector<const T>
, ale jest w porządku, gdy vector<T>
T ma element const).
address
funkcji składowych w domyślnym alokatorze: gdy T jest stała, te dwa przeciążenia mają ten sam podpis. Łatwym sposobem naprawienia tego byłoby wyspecjalizowanie sięstd::allocator<const T>
i usunięcie jednego z przeciążeń.push_back
. Ale jeśli nie pozwala na to projekt, lepiej tego nie robić. Byłem tylko ciekawy.std::vector<const T>
dokładnie dlatego, że jest bardzo podobny doconst std::vector<T>
, ale bez negatywnych konsekwencji tego ostatniego dla klasy, która go trzyma. W rzeczywistościstd::vector<const T>
jest DOKŁADNIE tym, czego potrzebuję semantycznie w większości przypadków, w których używamvector
. Teraz muszę rzucićconst
- wraz z niezawodnością, jaką zapewnia.Aktualizacja
Pod zaakceptowaną (i poprawną) odpowiedzią skomentowałem w 2011 roku:
Wydaje mi się, że w nadchodzącej wersji roboczej C ++ 17 zalegalizowaliśmy
vector<const T>
i uważam, że zrobiliśmy to przypadkowo . :-)P0174R0 usuwa
address
przeciążenia zstd::allocator<T>
. P0174R0 nie wspomina o wsparciustd::allocator<const T>
jako części uzasadnienia.Korekta
W komentarzach poniżej TC słusznie zauważa, że
address
przeciążenia są przestarzałe , a nie usuwane. Mój błąd. Nieaktualni członkowie nie pojawiają się w 20.10.9, gdziestd::allocator
zdefiniowano, ale zamiast tego są przenoszeni do sekcji D.9. Kiedy to opublikowałem, zaniedbałem przeglądanie rozdziału D pod kątem takiej możliwości.Dziękuję TC za korektę. Zastanawiałem się nad usunięciem tej mylącej odpowiedzi, ale być może najlepiej zostawić ją z tą poprawką, aby być może uchroni to kogoś przed błędnym odczytaniem specyfikacji w taki sam sposób, jak ja.
źródło
address
.vector<const T>
:)Chociaż mamy już bardzo dobre odpowiedzi na ten temat, zdecydowałem się przedstawić bardziej praktyczną odpowiedź, aby pokazać, co można, a czego nie można zrobić.
Więc to nie działa:
vector<const T> vec;
Po prostu przeczytaj pozostałe odpowiedzi, aby zrozumieć, dlaczego. Jak można się domyślić, to też nie zadziała:
vector<const shared_ptr<T>> vec;
T
już nie jestconst
, alevector
trzymashared_ptr
s, nieT
s.Z drugiej strony, to robi pracę:
vector<const T *> vec; vector<T const *> vec; // the same as above
Ale w tym przypadku const jest wskazywanym obiektem, a nie samym wskaźnikiem (który jest tym, co przechowuje wektor). Byłoby to równoważne z:
vector<shared_ptr<const T>> vec;
Co jest w porządku.
Ale jeśli umieścimy
const
na końcu wyrażenia, zmieni on teraz wskaźnik w aconst
, więc następujące elementy nie zostaną skompilowane:vector<T * const> vec;
Zgadzam się, trochę zagmatwane, ale przyzwyczajasz się do tego.
źródło
Uzupełniając inne odpowiedzi, innym podejściem jest użycie:
vector<unique_ptr<const T>> vec;
Jeśli jest to przypadek, w którym chcesz wyegzekwować, że
vec
ma tylko własność swoich elementów. Lub jeśli chcesz dynamicznie przenosić elementy dovec
i w pewnym momencie je przenosić.Jak podkreślił, wskaźnik
const
semantyka może być mylące, aleshared_ptr
iunique_ptr
nie są.const unique_ptr<T>
jest wskaźnikiem do stałej iunique_ptr<const T>
jest punktem stałym, jak można się spodziewać.źródło