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?
Respuesta
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.
"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'. –
@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
@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. –
- 1. Servicios RIA OData "Las opciones de consulta no están permitidas".
- 2. ORA-30483: las funciones de ventana no están permitidas aquí
- 3. ¿Por qué las estructuras estáticas no están permitidas en C#?
- 4. ¿Qué unidades están permitidas en google.maps.Size?
- 5. C++ operaciones de iterador LINQ-like
- 6. Solo las consultas de Ancestor están permitidas dentro de las transacciones, ¿cómo manejarlas?
- 7. Scala mutable BitSet, ¿dónde están las operaciones de mutación?
- 8. ¿Qué operaciones en las colecciones paralelas de Scala están paralelizadas?
- 9. ¿Qué rango de fechas están permitidas en Javascript?
- 10. ¿Por qué las especializaciones de plantillas no están permitidas en diferentes espacios de nombres?
- 11. Restricción de verificación - Las subconsultas no están permitidas en este contexto
- 12. Las expresiones solo están permitidas como el primer elemento de una canalización
- 13. ¿Por qué las interfaces no están permitidas como miembros de anotación?
- 14. ¿Existe un iterador cíclica estándar en C++
- 15. Autenticación básica de Apache, excepto las permitidas
- 16. ¿Por qué las variables protegidas no están permitidas por defecto en Checkstyle?
- 17. SQL de las operaciones
- 18. ¿Cómo realizar una implementación personalizada de un iterador estándar?
- 19. Número máximo de cookies permitidas
- 20. ¿Cómo puedo enumerar todas las operaciones de WCF que se están ejecutando actualmente?
- 21. LinqDataSource no admite la propiedad Seleccionar cuando las operaciones Eliminar, Insertar o Actualizar están habilitadas
- 22. ¿Qué partes de UIKit, Core Graphics, Core Animation, OpenGL están permitidas en no main-thread?
- 23. ¿Cómo se definen las etiquetas permitidas en CKEditor?
- 24. ¿Dónde están todos los recursos estándar de íconos de Android?
- 25. ¿Se están ejecutando las bibliotecas estándar para los filtros de Bloomier?
- 26. ¿Qué cadenas están permitidas en el atributo "nombre común" en un certificado X.509?
- 27. Rehacer las clases estándar
- 28. ¿Cambiar las operaciones de diario en .NET?
- 29. preprocesadores C y orden de las operaciones
- 30. R: acelerar las operaciones de "agrupar por"
"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. –
@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
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. –