2012-11-18 15 views
5

Poniżej znajduje złe:Konst-Poprawność dla elementów kontenerów std

vector<const int> vec; 

Problem polega na tym, że typ szablonu musi być przypisane. Poniższy kod kompiluje [EDIT: w Visual Studio 2010], wykazując problem z powyższym:

vector<const int> vec; 
vec.push_back(6); 
vec[0] += 4; 

Przy bardziej skomplikowanych rodzajów, może to być poważny problem.

Moje pierwsze pytanie dotyczy tego, czy istnieje powód takiego zachowania. Wydaje mi się, że może być możliwe utworzenie kontenerów const, które uniemożliwiają powyższe i niestanowiące kontenerów, które na to pozwalają.

Po drugie, czy istnieje sposób na tworzenie kontenerów, które działają w ten sposób?

Po trzecie, co się tutaj dzieje (z typem użytkownika)? Rozumiem, że jest to niezdefiniowane zachowanie, ale w jaki sposób STL w ogóle to kompiluje?

+2

Używasz standardowego libra w sposób, który jest niezdefiniowanym zachowaniem. Oznacza to, że * nie ma żadnych * wymagań co do tego, co powinno się wydarzyć. Niektóre operacje mogą wydawać się działać, inne nie. Nie można oczekiwać spójności między różnymi implementacjami. –

+1

To nie kompiluje się na g ++ 4.6.3. –

+1

Twój kod nie kompiluje się ze standardem C++. –

Odpowiedz

3

Powodem, dla którego std::vector<T const> nie jest dozwolone, może być konieczne przetasowanie obiektu w wektorze podczas wstawiania w innym miejscu niż początek. Teraz, członek std::vector<T>::push_back(T const& v) jest koncepcyjnie równoważne (pozostawiając parametr szablonu podzielnik się, jak to jest bez znaczenia dla tej dyskusji)

template <typename T> 
void std::vector<T>::push_back(T const& v) { 
    this->insert(this->end(), v); 
} 

który wydaje się być, jak to jest realizowane w niektórych implementacjach. Operacja ta wymagałaby na ogół, aby niektóre obiekty mogły zostać przeniesione, dlatego też konieczne jest przypisanie argumentu T. Wygląda na to, że standardowa dostawa bibliotek z MSVC++ nie deleguje operacji, ale wykonuje wszystkie niezbędne operacje, tj. Zmienia rozmiar tablicy i przenosi obiekty odpowiednio, gdy zabraknie miejsca, w push_back(). Nie jest całkiem jasne, jakie wymagania są na typie T, aby móc korzystać z push_back().

Zasadniczo, pojemnik wspieranie zarówno T const i operację w środku insert() byłoby możliwe, ale: Nic nie wymaga pamięci wewnętrznej być T zamiast typename std::remove_const<T>::type natomiast wystawienie T& w interfejsie. Należy zachować ostrożność w zakresie operacji const -wersja, takich jak operator[](), ponieważ po prostu użycie T const& jako typu zwrotnego, gdy T jest typu pewnego typu , może skutkować typem S const const. W C++ 2003 byłby to błąd, w C++ 2011 myślę, że const są po prostu zwinięte. Aby być bezpiecznym, możesz użyć typename std::add_const<T>::type&.

Powiązane problemy