2011-10-18 9 views
5

estoy consiguiendo error siguiente error: invalid conversion from ‘const int*’ to ‘int*’ siguiente es mi programaconversión no válida del 'const int *' a 'int *', teniendo std :: set dirección del 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))); 
} 

Quiero dirección del elemento en el std::set, Este código no da ningún error de compilación con el compilador de Microsoft pero g++ está dando este error de compilación.

+0

Los elementos de std :: set son constantes, en su caso enteros constantes. ¿Qué compilador de MS estás usando? – cpx

+0

Visual Studio 2005 – Avinash

+2

Es un error en VS2005 que permite modificar std :: set. – cpx

Respuesta

5

Es porque cada elemento de std::set se almacena como T const, y la implementación tiene una razón para hacerlo.

Dado que std::set contiene exactamente una sola copia de un valor. Tiene que hacerlo inmutable, de lo contrario, uno puede cambiar su valor a algo que ya existe en el conjunto.

Incluso si los elementos eran mutable, que no sería capaz el cambio del valor, porque std::set::find es una función const miembro, y por lo tanto en esta función intSet es inmutable y eficazmente cada elemento se convertiría en inmutable también, incluido el iterador que devuelve, y mediante el cual puede cambiar el valor en el sitio de llamada.

La única quieren tomar la dirección es la siguiente:

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

No utilice const_cast embargo,

//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

Como solo necesito la dirección del elemento, ¿estaría bien encasillar como no lanzado – Avinash

+0

@Avinash: I agregué más cosas a mi respuesta. – Nawaz

+0

Los elementos establecidos se almacenan como 'T', no' T const', y pueden modificarse siempre que no afecte el orden. El comportamiento de GCC, aunque es más seguro, no cumple. –

0

Los valores del conjunto están destinados a ser inmutable para que la clase puede garantizar que todos los elementos son únicos. Si le otorga un puntero que no sea const, le resultará demasiado fácil cambiar el valor, lo que rompería el diseño de la clase de plantilla establecida (http://msdn.microsoft.com/en-us/library/e8wh7665(VS.80).aspx).

Debe cambiar la última línea para tener un "const" en frente de ella, así:

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

FYI: El código da un error de compilación idéntica en Visual Studio 2010.

1

GCC definesset::iterator para ser set::const_iterator, evitando que vincule una referencia que no sea const o un puntero al resultado de set::find(). Este comportamiento está permitido por C++ 11 (que establece que las claves son inmutables, y que set::iterator es un iterador constante), pero que fue incorrecto en C++ 03.

En C++ 03, no debe modificar los elementos de un conjunto ya que eso puede interrumpir el orden de los elementos dentro de él. En algunos casos, es posible que desee: si el tipo es una clase y solo se usan algunos miembros para definir el orden, entonces era válido modificar otros miembros. El estándar C++ 03 permite esto, pero debe tener cuidado de no modificar el orden ya que eso le dará un comportamiento indefinido. En C++ 11, esto no está permitido, y la implementación puede evitar esto.

En su caso, no puede modificar legalmente el valor en absoluto, por lo que puede corregir su código para C++ 11, y también mejorar su seguridad, mediante el enlace a un puntero-a-const.

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

Qué estándar permite esto, porque en los requisitos de contenedor asociativo n3225 es bastante claro: "Para' conjunto' y 'multiset' el tipo de valor es el mismo que el tipo de clave. ... Las claves en un contenedor asociativo son ** inmutables * *. " y "Para contenedores asociativos donde el tipo de valor es el mismo que el tipo de clave, tanto el iterador como el const_iterator son ** iteradores constantes **. Es sin especificar si el iterador y el const_iterator son del mismo tipo o no". - Incluso se menciona en la discusión del informe de error que GCC se considera conforme. – UncleBens

+0

@UncleBens: Estaba buscando C++ 03, que no tiene esas cláusulas, pero especifica que 'iterator' es un" tipo de iterador que apunta a 'T'" para todos los contenedores. Actualizaré mi respuesta para C++ 11. –

Cuestiones relacionadas