Con una classe contenitore, ad esempio std::vector
, esistono due diversi concetti di costante: quello del contenitore (ovvero la sua dimensione) e quello degli elementi. Sembra che std::vector
confonde questi due, in modo tale che il seguente codice semplice non viene compilato:const vs non-const del contenitore e del suo contenuto
struct A {
A(size_t n) : X(n) {}
int&x(int i) const { return X[i]; } // error: X[i] is non-const.
private:
std::vector<int> X;
};
Si noti che anche se i membri di dati (i tre puntatori alla iniziano & fine dei dati e alla fine del buffer assegnato) di std::vector
sono non modificato da una chiamata al suo operator[]
, questo membro non è const
- non è uno strano design?
noti inoltre che per i puntatori prime, questi due concetti di costante-ness sono ben separati, in modo tale che il codice grezzo puntatore corrispondente
struct B {
B(size_t n) : X(new int[n]) {}
~B() { delete[] X; }
void resize(size_t n); // non-const
int&x(int i) const { return X[i]; } // fine
private:
int*X;
};
funziona bene.
Quindi qual è il modo corretto/consigliato per gestirlo quando si utilizza std::vector
(senza utilizzare mutable
)?
È un const_cast<>
come in
int&A::x(int i) const { return const_cast<std::vector<int>&>(X)[i]; }
giudicate accettabili (X
è noto per essere non const
, quindi non UB qui)?
EDIT proprio per prevenire ulteriore confusione: voglio modificare gli elementi, cioè i contenuto del contenitore ma non il contenitore stesso (la dimensione e/o posizione di memoria).
I dati di 'std :: VECTOR' potrebbe essere cambiato dalla vostra chiamata a' operatore [] '. Come hai scritto 'A :: X',' a.x (1) ++; 'è perfettamente legale e modifica il contenuto del vettore. –
@DavidSchwartz I * contenuti * di un vettore non sono i suoi effettivi * dati * (sebbene sia possibile associarli logicamente come tali). Se ispezionate 'std :: vector', ha solo 3 puntatori come dati (inizio e fine dei dati e fine del buffer). Questi rimangono invariati. – Walter