2011-10-18 11 views
5

sto ottenendo seguente errore error: invalid conversion from ‘const int*’ to ‘int*’ seguito è il mio programmaconversione non valida dal 'const int *' a 'int *' durante l'assunzione di std :: set indirizzo dell'elemento

#include <set> 
int main (int argc, char **argv) { 
    std::set<int> intSet; 
    intSet.insert(1); 
    intSet.insert(2); 
    intSet.insert(3); 
    intSet.insert(4); 
    intSet.insert(5); 

    int *pAddress = &(*(intSet.find(4))); 
} 

Voglio indirizzo del elemento nel std::set, Questo codice non fornisce alcun errore di compilazione con il compilatore Microsoft ma g++ sta dando questo errore di compilazione.

+0

Gli elementi di std :: set sono costanti, nel tuo caso interi costanti. quale compilatore MS stai usando? – cpx

+0

Visual Studio 2005 – Avinash

+2

È un bug in VS2005 che consente a std :: set di essere modificato. – cpx

risposta

5

È perché ogni elemento di std::set è memorizzato come T const e l'implementazione ha un motivo per farlo.

Poiché std::set contiene esattamente una singola copia di un valore. Deve farlo immutable, altrimenti, si può cambiare il suo valore in qualcosa che già esiste nel set.

Anche se gli elementi erano mutevole, non sarebbe in grado il cambiamento del valore, perché std::set::find è una funzione const membro, e quindi in questa funzione intSet è immutabile ed efficacemente ogni elementi diventerebbe immutabile pure, incluso l'iteratore che restituisce e tramite il quale è possibile modificare il valore nel sito di chiamata.

L'unica vuole prendere l'indirizzo è questo:

int const *paddress = &(*(intSet.find(4))); //const int* is same as int const* 

Non utilizzare const_cast però,

//DANGEROUS - DONT DO IT 
int *paddress = const_cast<int*>(&(*(intSet.find(4)))); //will compile, 
                 //but it is dangerous! 

//you might accidentally write 
*paddress = 10; //undefined behaviour, 
       //though the compiler will let you write this 
+0

Dal momento che ho solo bisogno di indirizzo dell'elemento, sarebbe ok per typecast a non lanciare – Avinash

+0

@Avinash: I aggiunto più cose alla mia risposta. – Nawaz

+0

Gli elementi impostati sono memorizzati come 'T', non' T const', e possono essere modificati finché non si influisce sull'ordinamento. Il comportamento del GCC, mentre è più sicuro, non è conforme. –

0

I valori del set sono destinate ad essere immutabile in modo che la classe può garantire che tutti gli elementi siano unici. Fornire un puntatore non const renderebbe troppo facile la modifica del valore, che interromperà il design della classe modello dell'insieme (http://msdn.microsoft.com/en-us/library/e8wh7665(VS.80).aspx).

Si dovrebbe cambiare l'ultima riga di avere un "const" di fronte ad essa in questo modo:

const int *pAddress = &(*(intSet.find(4))); 

FYI: Il codice dà un errore di compilazione identico in Visual Studio 2010.

1

GCC definesset::iterator da set::const_iterator, impedendo di associare un riferimento o un puntatore non const al risultato di set::find(). Questo comportamento è consentito da C++ 11 (che afferma che le chiavi sono immutabili e che set::iterator è un iteratore costante), ma non era corretto in C++ 03.

In C++ 03, non è necessario modificare gli elementi di un set poiché ciò può interrompere l'ordine degli elementi al suo interno. In alcuni casi, è possibile che si desideri - se il tipo è una classe e solo alcuni membri vengono utilizzati per definire l'ordine, allora era valido modificare altri membri. Lo standard C++ 03 consente questo, ma bisogna stare attenti a non modificare l'ordine in quanto ciò darà un comportamento indefinito. In C++ 11 questo non è permesso e l'implementazione potrebbe impedirlo.

Nel tuo caso, non puoi modificare legalmente il valore, quindi puoi correggere il tuo codice per C++ 11 e anche migliorarne la sicurezza, legandolo a un pointer-to-const.

int const *pAddress = &(*(intSet.find(4))); 
+2

Quale standard permette questo, perché nei requisiti container associativi n3225 è del tutto evidente: "Per' 'set' e multiset' il tipo di valore è lo stesso del tipo di chiave ... chiavi in ​​un contenitore associativo sono immutabili ** *. * ". e "Per i contenitori associativi in ​​cui il tipo di valore è uguale al tipo di chiave, sia iteratore che const_iterator sono ** iteratori costanti **. È non specificato se iteratore e const_iterator sono o meno dello stesso tipo." - Viene persino menzionato nella discussione sulla segnalazione di bug che GCC è considerato conforme. – UncleBens

+0

@UncleBens: Stavo guardando C++ 03, che non ha queste clausole, ma non specifica che 'iterator' è un "iteratore tipo che punta a 'T'" per tutti i contenitori. Aggiornerò la mia risposta per C++ 11. –

Problemi correlati