¿Cuál es la diferencia entre un const_iterator
y un iterator
y dónde se usaría uno sobre el otro?¿Cuál es la diferencia entre const_iterator y el iterador non-const en C++ STL?
Respuesta
const_iterator
s no le permiten cambiar los valores que señalan, iterator
s normal.
Como con todas las cosas en C++, siempre prefiera const
, a menos que haya una buena razón para usar iteradores regulares (es decir, desea utilizar el hecho de que no son const
para cambiar el valor apuntado).
Deberían ser casi autoexplicativas. Si el iterador apunta a un elemento de tipo T, entonces const_iterator apunta a un elemento de tipo 'const T'.
es básicamente equivalente a los tipos de puntero:
T* // A non-const iterator to a non-const element. Corresponds to std::vector<T>::iterator
T* const // A const iterator to a non-const element. Corresponds to const std::vector<T>::iterator
const T* // A non-const iterator to a const element. Corresponds to std::vector<T>::const_iterator
Un iterador const siempre apunta al mismo elemento, por lo que el iterador sí es const. Pero el elemento al que apunta no tiene que ser const, por lo que el elemento al que apunta se puede cambiar. Un const_iterator es un iterador que apunta a un elemento const, por lo que aunque el iterador mismo se puede actualizar (aumentar o disminuir, por ejemplo), el elemento al que apunta no se puede cambiar.
"Un iterador constante siempre apunta al mismo elemento," Esto es incorrecto. –
¿Cómo es eso? Tenga en cuenta el guion bajo que falta. Estoy contrastando una variable de tipo const std :: vector
Ah, ya veo. Sí, me perdí el guión bajo que faltaba. –
Uso const_iterator cada vez que pueda, utilice iterador cuando no tiene otra opción.
(como han dicho otros) const_iterator no le permite modificar los elementos a los que apunta, esto es útil dentro de los métodos de clase const. También le permite expresar su intención.
Unfortunaty, muchos de los métodos para los contenedores STL toma iteradores en lugar de const_iterators como parámetros. Entonces, si tiene const_iterator, no puede decir "inserte un elemento antes del elemento al que apunta este iterador" (diciendo que tal cosa no es conceptualmente una violación const, en mi opinión). Si desea hacer eso de todos modos, debe convertirlo a un iterador no const utilizando std :: advance() o boost :: next(). P.ej. boost :: next (container.begin(), std :: distance (container.begin(), the_const_iterator_we_want_to_unconst)). Si contenedor es std :: list, entonces el tiempo de ejecución para esa llamada será O (n).
Por lo tanto, la regla universal para agregar const donde sea que sea "lógico" hacerlo, es menos universal cuando se trata de contenedores STL.
Sin embargo, los contenedores de impulso toman const_iterators (por ejemplo, boost :: unordered_map :: erase()). Entonces, cuando usas contenedores de impulso puedes ser "const agresivo". Por cierto, ¿alguien sabe si los contenedores de STL serán reparados o cuándo?
Puede ser una cuestión de opinión. En el caso de 'vector' y' deque', insertar un elemento invalida todos los iteradores existentes, lo cual no es muy 'const'. Pero veo tu punto. Tales operaciones están protegidas por el contenedor 'const'-ness, no por los iteradores. Y me pregunto por qué no hay una función de conversión de iterador const-to-nonconst en la interfaz de contenedor estándar. – Potatoswatter
Usted es correcto Potatoswatter, soy categórico, es una cuestión de opinión para los contenedores de acceso aleatorio y ** container.begin() + (the_const_iterator_we_want_to_unconst - container.begin()) ** es ** O (1) * * de todas formas. También me pregunto por qué no hay una función de conversión para los contenedores de acceso no aleatorio, pero tal vez haya una buena razón. ¿Sabes si hay alguna razón por la cual las funciones para los contenedores de acceso no aleatorio no tengan ** const_iterators **? –
bien Voy a explicar con ejemplo muy simple primero sin utilizar iterador constante consideramos que tenemos colección de recogida de números enteros aleatorios "RandomData"
for(vector<int>::iterator i = randomData.begin() ; i != randomData.end() ; ++i)*i = 0;
for(vector<int>::const_iterator i = randomData.begin() ; i!= randomData.end() ; ++i)cout << *i;
Como puede verse por los datos de edición/escritura dentro de la colección iterador normales se usa, pero para fines de lectura se ha utilizado un iterador constante. Si intentas usar el iterador constante en el primer ciclo, obtendrás un error. Como regla general, usa el iterador constante para leer datos dentro de la colección.
ejemplos mínimos
iteradores no constante permiten modificar lo que apuntan a: iteradores
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);
Const no:
const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
Como puede observarse, v.begin()
es const
sobrecargado y devuelve iterator
o const_iterator
dependiendo de la const-dad de la variable contenedor:
- How does begin() know which return type to return (const or non-const)?
- how does overloading of const and non-const functions work?
Un caso común donde const_iterator
aparece es cuando this
se utiliza dentro de un método const
:
class C {
public:
std::vector<int> v;
void f() const {
std::vector<int>::const_iterator it = this->v.begin();
}
void g(std::vector<int>::const_iterator& it) {}
};
const
hace this
const, wh ich hace this->v
const.
Por lo general, puede olvidarse de ello con auto
, pero si comienza a pasar esos iteradores, tendrá que pensar en ellos para las firmas de método.
Al igual que const y no constante, puede convertir fácilmente de no-const a const, pero no a la inversa:
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
// non-const to const.
std::vector<int>::const_iterator cit = it;
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
// Compile time error: no conversion from const to no-const.
//it = ci1;
cuál usar: análogo a const int
vs int
: prefiera const iteradores siempre que pueda usarlos (cuando no necesite modificar el contenedor con ellos), para documentar mejor su intención de leer sin modificar.
- 1. Diferente eficiencia de iterador y const_iterator (STL)
- 2. C++ STL :: ¿cuál es la diferencia entre inplace_merge y sort
- 3. cuál es la diferencia entre mapa y hashmap en STL
- 4. ¿Diferencia de rendimiento entre el iterador ++ y el iterador ++?
- 5. ¿Cuál es la diferencia entre C++ administrado y C#?
- 6. ¿Cuál es la diferencia entre Managed C++ y C++/CLI?
- 7. ¿Cuál es la diferencia entre Visual C++ y C++?
- 8. cómo detectar si un tipo es un iterador o const_iterator
- 9. ¿Cuál es la diferencia entre 'int'? y 'int' en C#?
- 10. ¿Cuál es la diferencia entre File y FileInfo en C#?
- 11. ¿Cuál es la diferencia entre C y C incrustado?
- 12. ¿Cuál es la diferencia entre el conjunto <pair> y el mapa en C++?
- 13. ¿cuál es la diferencia entre atan y atan2 en C++?
- 14. ¿Cuál es la diferencia entre System.Type y System.RuntimeType en C#?
- 15. ¿Cuál es la diferencia entre printf() y puts() en C?
- 16. ¿Cuál es la diferencia entre Process y ProcessStartInfo en C#?
- 17. ¿Cuál es la diferencia entre strtok_r y strtok_s en C?
- 18. En C# ¿cuál es la diferencia entre ToUpper() y ToUpperInvariant()?
- 19. Cuál es la diferencia entre & y operadores & en C#
- 20. Cuál es la diferencia entre memset y memcpy en C
- 21. ¿Cuál es la diferencia entre Const y Static en C#?
- 22. Obtención de const_iterator del iterador
- 23. ¿Cuál es la diferencia entre el casting y la conversión?
- 24. ¿cuál es la diferencia entre:.! y: r !?
- 25. Cuál es la diferencia entre $ y jQuery
- 26. ¿Cuál es la diferencia entre Ctrl-C y SIGINT?
- 27. Objetivo-C: ¿Cuál es la diferencia entre forKey y forKeyPath?
- 28. ¿Cuál es la diferencia entre dict() y {}?
- 29. Cuál es la diferencia entre $ (...) y `...`
- 30. ¿cuál es la diferencia entre -C y gzipping un mysqldump?
En un mundo perfecto ese sería el caso. Pero con C++ const es solo tan buena como la persona que escribió el código :( – JaredPar
mutable existe por una muy buena razón. Se usa raramente, y al buscar en Google Code Search, parece haber un porcentaje razonable de usos válidos. es una herramienta de optimización muy poderosa, y no es como eliminarla, mejoraría la corrección de la const (* tospointerscoughandcoughreferencescough *) – coppro
Más como un poderoso truco. De todas las instancias que he visto del uso de la palabra clave 'mutable', todo menos uno era un indicador preciso de que el código estaba mal escrito y se necesitaba modificar como un truco para evitar los defectos. –