2012-02-19 18 views
5

Considere un iterador estándar donde es necesario asignar memoria para atravesar una estructura de datos. ¿Permite el estándar que un iterador arroje una excepción si no se puede asignar memoria? Como ejemplo, piense en un iterador de entrada para estructuras de datos de árbol. En este caso, para atravesar el árbol debe agregar y mantener un puntero al padre de cada nodo (lo que ralentizaría las operaciones que no necesitan dicho puntero, como insertar/borrar/buscar en el árbol) o usar una pila para ayudar al iterador a almacenar los punteros en los nodos atravesados. En este caso, al avanzar la pila podría crecer hasta que no haya más memoria libre y el iterador se vea obligado a tirar.¿Están permitidas las operaciones estándar de iterador?

+0

"En este caso, para atravesar el árbol, debe agregar y mantener un puntero al padre de cada nodo" Cada nodo * debe * tener un puntero a su elemento primario. De lo contrario, es un árbol "hacia adelante", donde solo puedes descender. Diría que un iterador que usaba una pila se rompería tanto para confiar en un objeto global como compartido (lo que lo haría no seguro para subprocesos) y para asignar memoria solo para atravesar el árbol. Tenga en cuenta que los iteradores para 'std :: forward_list' en C++ 11 son iteradores directos; usted * no puede * regresar en absoluto. –

+1

@Nicol ¿Quién dijo que la pila sería global o compartida? La pila está asociada a la instancia del iterador. Además, las pilas son probablemente la única forma de implementar * iteradores de entrada * en árboles donde los nodos tienen punteros solo para sus sucesores. – Martin

+0

Los iteradores de entrada no * insertan * elementos en la estructura de datos. Solo pueden leer y modificar elementos que ya existen. Los iteradores de salida pueden, pero notarán que la mayoría de ellos son adaptadores de iterador para * contenedores *, no iteradores. Y los nodos de los árboles deberían apuntar a sus padres. –

Respuesta

5

Sí, un método de iterador en C++ puede lanzar y, como ha señalado, puede arrojar en determinadas circunstancias.

La única clase de funciones en C++ que no puede lanzar es un destructor. Y realmente eso es solo por convención (porque hace que ciertas operaciones sean casi imposibles de hacer correctamente). Los destructores pueden arrojar, es muy malo dejarlos hacerlo.

Las funciones individuales se pueden marcar con throw() para evitar que se vuelquen.

+0

"La única función en C++ que no puede lanzar es un destructor". No es verdad. El estándar define bastantes funciones de biblioteca estándar que no pueden lanzar. Por ejemplo, la mayoría de los constructores de 'auto_ptr' se designan' throw() 'en C++ 03, lo que significa que no pueden lanzar. En C++ 11, casi todas las implementaciones de 'swap' se definen con' noexcept'. –

+0

@NicolBolas Intentaba hacer una declaración general sobre si se permitía lanzar una clase/tipo de función. El modificador 'throw()' ciertamente dice que una función individual no puede lanzar. Aunque agregaré una nota al respecto. No estoy familiarizado con 'noexcept', ¿tiene una buena página de referencia para eso? – JaredPar

+0

@JaredPar: se introdujo la nueva sintaxis en C++ 11. Que Visual C++ hasta ahora ha ignorado, aunque debería ser una de las cosas más fáciles de implementar (casi idéntico a 'throw()' + un rasgo de tipo). Ver la sección 15.4 y 5.3.7 del Estándar C++ 11. –

Cuestiones relacionadas