2012-11-18 12 views
5

Di seguito è male:Const-Correttezza per elementi di contenitori std

vector<const int> vec; 

Il problema è che il tipo di modello ha bisogno di essere assegnabili. Il seguente codice compila [EDIT: in Visual Studio 2010], dimostrando un problema con il sopra:

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

Con i tipi più complicati, questo può essere un problema serio.

La mia prima domanda è se esiste un motivo per questo comportamento. Mi sembra che sia possibile rendere contenitori const che non consentono i contenitori sopra e non-const che lo consentono.

In secondo luogo, c'è un modo per rendere contenitori che funzionano in questo modo?

In terzo luogo, cosa sta effettivamente accadendo qui (con un tipo di utente)? Mi rendo conto che è un comportamento indefinito, ma in che modo STL lo sta compilando?

+2

Si sta utilizzando la libreria standard in un modo non definito. Ciò significa che non ci sono * requisiti * su cosa dovrebbe accadere. Alcune operazioni potrebbero sembrare funzionare, altre no. E nessuna coerenza da aspettarsi tra diverse implementazioni. –

+1

Questo non si compila su g ++ 4.6.3. –

+1

Il tuo codice non viene compilato con C++ standard. –

risposta

3

Il motivo std::vector<T const> non è consentito è che l'oggetto in un vettore potrebbe dover essere rimescolato quando si inserisce in un punto diverso rispetto all'inizio. Ora, il membro std::vector<T>::push_back(T const& v) è concettualmente equivalente (lasciando il parametro di template allocatore come è irrilevante per questa discussione)

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

che sembra essere come viene implementato in alcune implementazioni. Ora, questa operazione richiede, in generale, che alcuni oggetti possano aver bisogno di essere spostati e, quindi, l'argomento T deve essere assegnabile. Sembra che la spedizione della libreria standard con MSVC++ non deleghi l'operazione ma esegua tutta la gestione necessaria, ovvero ridimensionando l'array e spostando gli oggetti in modo appropriato quando si esaurisce lo spazio, in push_back(). Non è abbastanza chiaro quali siano i requisiti del tipo T per poter utilizzare push_back().

In linea di principio, un contenitore di supporto sia T const e un insert() operazione nel mezzo sarebbe possibile, però: Nulla richiede la memorizzazione interna sia T anziché typename std::remove_const<T>::type esponendo un T& nell'interfaccia. È necessario essere un po 'attenti alla const -versione di operazioni come operator[]() perché usare solo T const& come tipo di ritorno quando T è un tipo S const risulterebbe in un tipo S const const. In C++ 2003 questo sarebbe un errore, in C++ 2011 penso che lo const sia appena collassato. Per sicurezza, è possibile utilizzare typename std::add_const<T>::type&.

Problemi correlati