2011-04-12 16 views
12

consideran este código de ejemplo:¿Por qué std :: set.insert() devuelve un iterador no const y, sin embargo, no puedo modificarlo?

#include <set> 
#include <string> 

using namespace std; 

set<string> string_set; 

void foo(const string& a) 
{ 
    pair<set<string>::iterator, bool> insert_result = string_set.insert(a); 

    string& val = *(insert_result.first); 
    val += " - inserted"; 
} 

Por lo tanto, la corrección a un lado, como no comprobar para la inserción exitosa y así sucesivamente, este código parece que debería permitir que me de modificación de la cadena después de la inserción, pero el compilador (VS2010) prohíbe desreferenciar el iterador a una cadena no const (estamos migrando desde VS2005 que agitó esto sin una advertencia).

Ahora, sé que esto debería estar prohibido, ya que puede hacer que la cadena no sea única, y estoy contento de que funcione de esta manera, pero en el caso real no es tan claro como eso, ya que Quiero enmendar un miembro de datos no mutable que no participe en las pruebas de equivalencia u orden.

Lo que quiero saber es, ¿cómo sabe el compilador que no puedo hacer esto, y cómo sé sin referencia a la documentación (que no menciona esto de todos modos)?

Saludos, Guy

Respuesta

23

Porque según la norma, las modificaciones a través de a set<>::iterator no están permitidas. El estándar específicamente permite que set<>::iterator y set<>::const_iterator sean el mismo tipo de . Y aunque no requiere que sean del mismo tipo , sí requiere el value_type de set<>::iterator a sea const.

La razón de esto, por supuesto, es que cualquier modificación en el valor podría invalidar las invariantes de std::set<>.

3

de la norma:

23.3.3

Un conjunto es una especie de asociativa contenedor que soporta claves únicas (contiene a lo sumo uno de cada clave valor) y proporciona una recuperación rápida de las claves . El conjunto de clases admite iteradores bidireccionales.

Ésta es también de la norma:
aplicación typedef define iterador; // Ver 23.1

La implementación real de set :: iterator es un iterador constante para mantener el requisito de tener claves únicas. De lo contrario, podría cambiar los valores en conjunto a todos los mismos valores.

+0

No creo que devuelva 'const_iterator', creo que es el' primer' miembro, que es const. –

+0

@Michael El estándar dice que es implementación definida. Ver edit –

+0

@Michael: no hay 'first' para un' set', estás confundiendo con un 'map' creo, que almacena un' pair '. –

Cuestiones relacionadas