2011-03-26 22 views
9

La sección §24.1/5 del estándar de C++ (2003) lee,¿Qué son los valores singulares y no singulares en el contexto de los iteradores de STL?

Así como un puntero normal a una matriz garantiza que existe un valor de puntero que apunta más allá del último elemento de la matriz, por lo que para cualquier tipo de iterador hay un valor de iterador que apunta a pasando el último elemento de un contenedor correspondiente . Estos valores se llaman valores pasados. Los valores de un iterador i para los cuales se define la expresión * i se llaman desreferenciables. La biblioteca nunca supone que los valores pasados ​​son desmarcables. Los iteradores también pueden tener valores singulares que no sean asociados a cualquier contenedor. [Ejemplo:. Después de la declaración de un puntero no inicializado x (como con int * x;), x debe ser siempre supone que tienen un valor singular de un puntero] Resultados de la mayoría de expresiones son indefinido para valores singulares; la excepción única es una asignación de un valor no singular a un iterador que tiene un valor singular. En este caso el valor singular se sobrescribe de la misma manera que cualquier otro valor. Los valores deducibles siempre son no singulares.

realmente no podía entender el texto mostrado en negrita ?

  • ¿Qué es el valor singular y el valor no singular? ¿Cómo se definen? ¿Y donde?
  • How y por qué valores desreferenciables son siempre nonsingular?

Respuesta

8

iteradores también puede tener valores singulares que no están asociados con cualquier recipiente.

Supongo que esa es su definición.

¿Cómo y por qué los valores sin referencias son siempre no singulares?

Porque si no lo hicieran, quitarles la referencia sería un comportamiento indefinido.

8

Si entiendo esto correctamente, un valor singular para un iterador es esencialmente el equivalente de un puntero no asignado. Es un iterador que no se ha inicializado para apuntar a ningún lado y, por lo tanto, no tiene un elemento bien definido sobre el que se esté iterando. La declaración de un nuevo iterador que no está configurado para apuntar a un elemento de un rango, por ejemplo, crea ese iterador como un iterador singular.

Como se refiere a la parte de la especificación, los iteradores singulares no son seguros y no se puede utilizar ninguna de las operaciones de iterador estándar, como incremento, asignación, etc. Todo lo que puede hacer es asignarles un nuevo valor, con suerte apuntarlos a datos válidos.

creo que la razón de tener esta definición es para que declaraciones como

set<int>::iterator itr; 

se puede permitir por la especificación mientras que tener un significado estandarizado. El término "singular" aquí probablemente se refiere a la definición matemática de una singularidad, que también se llama "discontinuidad" en contextos menos formales.

+0

¿Puede un 'istream_iterator' por defecto ser considerado singular? –

+1

No lo creo. Es un iterador pasado válido. Si fuera singular, no podría usarlo para definir el enf de una secuencia, ya que no podría compararlo con ningún otro iterador. – templatetypedef

2

Eche un vistazo a What is an iterator's default value?.

Como indica la cita, los valores singulares son valores de iterador que no están asociados con ningún contenedor. Un valor singular es casi inútil: no se puede avanzar, desreferenciarlo, etc. Una forma (¿la única forma?) De obtener un iterador singular es no inicializarlo, como se muestra en la respuesta de templatetypedef.

Una de las cosas útiles que puede hacer con un iterador singular, es asignar un valor no singular. Cuando lo haces, puedes hacer lo que quieras con él.

Los valores no singulares son, casi por definición, valores de iterador que son asociados a un contenedor. Esto responde por qué los valores sin referencias siempre son no singulares: los iteradores que no apuntan a ningún contenedor no pueden ser desreferenciados (¿qué elemento devolvería esto?).

Como Matthieu M. señaló correctamente, los valores no singulares aún pueden ser no desreferenciables. Un ejemplo es el iterador pasado-al-fin (que se puede obtener llamando al contenedor.end()): está asociado a un contenedor, pero todavía no se puede referenciar.

No puedo decir dónde se definen estos términos. Sin embargo, Google tiene esto que decir acerca de "definir: singular" (entre otras definiciones):

remarkable: unusual or striking 

supongo que esto puede explicar la terminología.

+1

¡Cuidado! Los valores no singulares incluyen el último iterador final, este no se puede desreferenciar. –

+0

@ Matthieu: tienes el 100% de razón. He actualizado mi respuesta para reflejar que los valores no singulares aún pueden ser no desreferenciables. ¡Gracias! – telewin

2

¿Qué es el valor singular y el valor no singular? ¿Cómo se definen? ¿Y donde?

Usemos la encarnación más simple de un Iterator: el puntero.

Para un puntero:

  • el valor singular aludido es el valor NULL un valor no inicializado.
  • un valor no singular es un valor inicializado de forma explícita, puede que no sea dereferencable todavía (el puntero past-the-final no se eliminan las referencias)

diría que el puntero NULL es un valor singular , aunque no el único, ya que representa la ausencia de valor.

¿Cuál es la equivalencia para los iteradores regulares?

std::vector<int>::iterator it;, el constructor por defecto de la mayoría de los iteradores (los vinculados a un recipiente) crear un valor singular. Como no está vinculado a un contenedor, cualquier forma de navegación (incremento, disminución, ...) no tiene sentido.

¿Cómo y por qué los valores sin referencias son siempre no singulares?

Los valores singulares, por definición, representan la ausencia de un valor real. Aparecen en muchos idiomas: Python's None, C# 's null, NULL de C, std::nullptr de C++. La trampa es que en C o C++, también pueden ser simples basura ... (lo que haya antes en la memoria)

¿Es un iterador construido por defecto un valor singular?

No necesariamente, supongo. No es requerido por el estándar, y uno podría imaginar el uso de un objeto centinela.

+0

Estaba pensando en la misma línea que tú, con * singular * iteradores que se refieren a cosas como un puntero nulo o 'std :: istream_iterator ()', pero luego volví a leer un par de veces la cita y llegué a la conclusión que este podría no ser el caso. Existe una garantía de que no solo puede asignar, sino también comparar punteros nulos (o 'std :: istream_iterator ()' Así que ya no estoy convencido de que esta interpretación sea válida. –

+0

@David: Creo que el estándar no está claro aquí El uso de * la mayoría de * seguir por * la única excepción * es dudoso, ¿por qué no * todo */* excepto *? Parecía que estaban dispuestos a dar cuenta de los valores unificados también (como el ejemplo) y no solo valores nulos –

+0

"el valor singular aludido a" es en realidad _not_ 'NULL'. El texto de ejemplo citado es claro:" Después de la declaración de un puntero x no inicializado (como con 'int * x; '), siempre se debe asumir que x un valor singular de un puntero. ". Ahora, un puntero no inicializado no es' NULL'. Ni siquiera se puede comparar con 'NULL'. – MSalters

Cuestiones relacionadas