2015-03-31 15 views
7

Następujące elementy nie są kompilowane (bardzo szczegółowy błąd, ale w zasadzie "nie można przeciążyć" i "nieprawidłowa konwersja z" const void * "na" void * ""). Mogę zrozumieć, dlaczego na przykład push_back() nie może skompilować, ponieważ nie można skopiować/przenieść do Foo* const, ale dlaczego nie ma tej kompilacji:wektor wskaźników const?

#include <vector> 
using namespace std; 

class Foo; 

int main() 
{ 
    vector<Foo* const> vec; 
} 
+1

Pełny błąd można znaleźć [tutaj] (http://ideone.com/EouxNT) –

+0

W C++ 03 element wektorowy musiał być CopyAssignable. W C++ 11 nadal nie jest dozwolone, [patrz tutaj] (http://stackoverflow.com/questions/6954906/does-c11-allow-vectorconst-t). W rzeczywistości sugeruję zamknięcie jako duplikat tego pytania, jeśli wszyscy się zgodzą. –

+0

Jak myślisz, w jaki sposób możesz wstawić nowe elementy do 'wektora'? – Jagannath

Odpowiedz

10

wektor jest prawdopodobnie jedynym pojemnik, który wymaga elementy mają być copy assignable. Dzieje się tak, ponieważ gwarantuje się, że elementy będą przechowywane w pamięci w sposób ciągły. Jeśli więc przekroczysz pojemność, należy przydzielić nowy fragment i ponownie przypisać elementy. Nie można tego zrobić z elementami const.

Ten sam błąd, jeśli próbujesz std::vector<const int>, lub w rzeczywistości dowolny typ const.

+1

Dlaczego przypisanie ponownego przydziału jest potrzebne? Brzmi bardziej, jakby potrzebował możliwości kopiowania ... –

+0

@KerrekSB: Z punktu widzenia przypisania kompilatora i kopiowalności sprowadza się to samo. – datenwolf

+0

Nie ma żadnych typów stałych; powinno działać, gdy operator przypisania jest stały. – rightfold

1

Zgłaszanie wektora zawierającego wskaźnik const Foo oznacza, że ​​wskaźnika nie można zmodyfikować. Gdy wstawisz element do wektora, musisz napisać do const pointer (nieważny).

Jesteś pewien, że to nie jest: std::vector<Foo const *> vec;, gdzie Foo nie mogą być modyfikowane przez wskaźnik.

1

Słowo kluczowe C/C++ const jest skojarzone lewostronnie, tzn. Wpływa na token po jego lewej stronie, z wyjątkiem przypadku, gdy const jest pierwszym tokenem w wyciągu. Tak więc void *const oznacza "stały (= niezmienny) wskaźnik do unieważnienia".

Stąd semantyka:

int a; 
void * const ptr = (void*)&a; /* legal */ 

int b; 
ptr = (void*)&b; /* not permitted */ 

później jest zabronione, ponieważ zmienne const musi być zainicjowany w definicji i nie mogą być zmienione później.

Podczas pisania std::vector<void * const> pytasz kompilator, aby wstawił szablon jako wektor niezmiennych wskaźników do unieważnienia. Jednak niezmienne oznacza, że ​​można go przypisać tylko z definicji, która jednak nie lata z dynamiczną naturą std::vector.

3

Elementy wektorowe muszą być przypisywane do wielu operacji: Jeśli wstawisz element w środku wektora, wszystkie późniejsze elementy muszą zostać ponownie przypisane. Zwykle typy const nie mogą być przypisywane.

Jeśli nie wykonasz operacji wymagających przypisania, nadal możesz używać wektorów o typach nieprzenoszalnych.

Można jednak użyć tylko std::allocator<T>, gdy T jest nie const typem obiektu, więc std::vector<const int> jest źle sformułowany.

+0

Ponieważ elementy wektorowe C++ 11 nie muszą być przypisywane –

+0

@MattMcNabb: Absolutnie prawo, edytowane. –

+0

@MattMcNabb hmmmm, g ++ 4.9.2 i nawet gcc5 uważa inaczej, ale tak, masz rację – vsoftco

Powiązane problemy