2012-07-10 19 views
8

estaba leyendo el C++ FAQ - "8.6 - When should I use references, and when should I use pointers?" y, en particular, esta declaración:¿Por qué no hay "referencia NULL" en C++?

Utilizar referencias cuando se puede, y los punteros cuando tienen que hacerlo.

...

La excepción a lo anterior es que el valor del parámetro o el retorno de una función necesita un "centinela" de referencia - una referencia que no se refiere a un objeto. Por lo general, esto se realiza mejor al devolver/tomar un puntero y al darle al puntero NULL este significado especial (las referencias siempre deben tener alias de objetos, no un puntero NULL sin referencias).

Por lo que he visto, la necesidad de una referencia "centinela" es a menudo la razón para usar punteros en lugar de referencias. Lo que me pregunto es: ¿por qué C++ no tiene un "valor nulo" especial para las referencias? Parece que haría los punteros casi innecesarios, lo que resolvería muchos problemas.

¿Por qué no era parte de la especificación del lenguaje?

Editar:

No estoy seguro de que mi pregunta es clara - Supongo que no estoy pidiendo literalmente sobre referencias nulas. Muy a menudo leo que en C++ "la referencia es el objeto". Y, en la mayoría de los lenguajes de OOP, los objetos pueden ser NULL - Pascal, C#, Java, JavaScript, PHP, etc. en todos estos puede hacer someObject = null o someObject := nil. De hecho, Pascal también admite punteros pero aún permite que los objetos sean nil, ya que tiene su uso. Entonces, ¿por qué C++ es de alguna manera especial y no tiene un objeto NULL? ¿Fue solo un descuido o una decisión real?

+1

Pray decir cómo eso eliminaría la necesidad de punteros? –

+3

@nathanwhite Porque entonces las referencias serían azúcar sintáctico para punteros, presumiblemente, que podrían usarse siempre que los punteros lo sean. Lo cual, IMO, eliminaría por completo algunos de los beneficios de las referencias. – hvd

+4

Leer [¿Por qué C++ tiene punteros y referencias?] (Http://www2.research.att.com/~bs/bs_faq2.html#pointers-and-references) y [C++: referencia nula] (http://stackoverflow.com/questions/4364536/c-null-reference). –

Respuesta

13

Porque una referencia lleva la semántica que apunta a una dirección de memoria válida que nunca cambia; es decir, que la eliminación de referencias es segura/definida y, por lo tanto, no se requieren verificaciones NULL. Las referencias no pueden ser reasignadas por diseño.

Utiliza un puntero cuando la var puede ser NULL y el código del cliente tiene que manejar ese caso. Utiliza una referencia cuando puede garantizar una dirección de memoria válida/inicializada.

Un ejemplo del uso de punteros es como miembro de una clase para almacenar una "referencia" a alguna instancia que podría no conocerse o no poder inicializarse en el momento de la construcción de la clase. Sin embargo, las referencias de los miembros deben inicializarse en el momento de la construcción (a través de las listas de inicializadores) y su asignación no puede diferirse.

Si permite que una referencia nula es entonces no es diferente a un puntero, además de la sintaxis (las mismas comprobaciones NULL tendrían que tener lugar.)

Actualización:

"Y, en la mayoría de los lenguajes de programación orientada a objetos, los objetos pueden ser NULL: Pascal, C#, Java, JavaScript, PHP, etc. [...] Entonces, ¿por qué C++ es de alguna manera especial y no tiene un objeto NULL? ¿Fue solo un olvido o una decisión real? ?"

creo que estás un poco confundido acerca de esto. Java y C#, etc. podría dar la impresión de 'objetos NULL', pero estas referencias a objetos son más o menos como un C puntero ++ con sintaxis más simple, GC instrumentación y lanzar una excepción. en estos idiomas si opera en un "objeto nulo" obtendrá algún tipo de excepción como NullReferenceException (C#). infierno, en Java que su llamado una NullPointerException .

tienes para comprobar null antes de que pueda usarlos de forma segura. Algo así como C++ poi nters (excepto en la mayoría de los lenguajes administrados, los punteros se inicializan a NULL de forma predeterminada, mientras que en C++ depende de usted configurar el valor del puntero inicial (de lo contrario no está definido/cualquier memoria que ya haya allí)).

vista El C++ se trata de tener la opción, y por lo tanto de manera ampliada:

  • utilizar un puntero normal que ver cómo favor, comprobar NULL en caso necesario.
  • Utilice referencias que tengan una validez/semántica validada por el compilador.
  • Haga rodar sus propios indicadores inteligentes que hacen la contabilidad y se comportan de la forma que desee.
  • Uso de punteros vacíos (¡con precaución!) Para hacer referencia a un bloque de memoria sin tipo si alguna vez se requiere.
+2

Nit: un puntero nulo y un puntero no inicializado son dos cosas diferentes. No se puede detectar un puntero no inicializado, al menos no confiablemente, porque podría apuntar a cualquier parte, incluso a un objeto válido. – hvd

+0

@hvd gracias y corregido. Por no inicializado realmente quise decir NULL. Se agregó una sección sobre ctors para ilustrar un uso distintivo de punteros. –

0

La referencia debe hacer referencia a algo, por lo tanto, la referencia nula no está disponible.
C no tiene referencias y solo podemos utilizar punteros en este idioma, por lo que es compatible con el lenguaje C

1

La referencia, por definición, debe estar asociada a otra variable u objeto. Entonces, una referencia vacía o nula viola su propósito de existencia.

Técnicamente eso significaría que comienzas con una referencia nula, luego ASIGNAR a alguna variable o puede reasignarse a otra variable. Esto simplemente NO es para lo que se creó la referencia.

Existen varios otros usos de los punteros que la referencia simplemente no se puede replicar. Como hacer referencia a una gran cantidad de datos complejos (una secuencia de bytes) con una pequeña cantidad de memoria con un puntero y pasarlos con la frecuencia que sea necesaria gastando solo 8 bytes más o menos para el puntero. No puede hacer eso con una referencia sin desperdiciar la misma memoria.

La referencia siempre estaría vinculada a un tipo, que no es el caso con el puntero.

+0

Los primeros 2 párrafos son correctos. El último no tiene significado. – wandalen

+0

Definitivamente tenía en mente un caso de uso que puede o no haber sido elaborado correctamente aquí. Pero por encima del comentario sin elaboración o incluso opinión, simplemente "no tiene sentido" es aún más inútil y no lleva a weightage – fayyazkl

6

Mire las diferencias entre los punteros y las referencias: mientras que la norma deja abierta la forma en que se implementan las referencias, en este momento se implementan siempre como punteros.

Lo que significa que la principal diferencia entre ellos es a) semántica b) los punteros se pueden volver a colocar c) los punteros pueden ser nulos.

Así que la respuesta corta es que esto se hizo a propósito. Cuando usted como programador vea una referencia, debe saber que a) esa referencia se rellena b) no cambiará (yc) puede usarla con la misma semántica que un objeto).

Si el estándar permitiera una referencia nula, siempre tendría que verificar el valor nulo antes de usar una referencia, que no era deseada.

Editar:

Con respecto a su edición, supongo que la confusión en este punto podría deberse al hecho de que la mayoría de los lenguajes orientados a objetos más simples ocultan lo que está pasando. Para tomar Java como ejemplo, mientras parece que tiene objetos NULL, y puede asignarlos, realmente no puede - lo que realmente está sucediendo es que Java solo tiene punteros, y puede asignar valores nulos a esos punteros. Como es imposible tener objetos directamente en Java, eliminan la semántica del puntero y tratan el puntero como el objeto. C++ es simplemente más poderoso y propenso a errores (los entusiastas de Java dirían que las instancias de la clase de usuario de la pila no son necesarias, y la decisión de no tenerlas en Java fue llevada a reducir la complejidad y hacer que Java sea más fácil de usar). También se deduce que, dado que Java no tiene objetos, no tiene referencias. Lo que realmente no ayuda, sin embargo, es que Java llama a lo que una persona de C++ llamaría un pase por valor de un puntero de paso a paso.

+0

He actualizado mi pregunta. ¿Cómo explicarías que casi todos los lenguajes OO permiten referencias 'null', pero C++ no? En todos estos otros idiomas, no siempre es necesario verificar NULL, depende completamente del contexto. –

+3

No conozco tantos lenguajes de OO, pero para los que hago no estoy de acuerdo. Java ni siquiera tiene referencias, Java solo tiene punteros (por ejemplo, puede ser nulo, puede reabrirse), aunque con una sintaxis diferente. Una de las razones por las que Java no tiene referencias es porque Java tampoco tiene variables de pila (excepto los tipos incorporados): todo es montón, cada variable es un puntero, por lo tanto puede ser nulo, sin memoria de pila, sin necesidad de referencias. Lo mismo vale para vba. Eso es casi todos los OO idiomas que conozco. – Cookie

+2

Considere, por ejemplo,un caso de uso típico de referencias en C++: tiene algunas variables asignadas de gran pila y desea pasarlas por referencia en lugar de valor. Aquí debe usar referencias C++ verdaderas, y es correcto hacerlo, porque deben ser no nulas y no cambiarán. En Java, no puede tener variables de pila, por lo que el entorno de llamada siempre tendrá punteros de todos modos, por lo que no necesita una construcción para pasar por referencia. A menudo hay confusión: lo que las personas de Java llaman "paso por referencia", las personas de C++ realmente deberían llamar "pasar por el puntero". – Cookie

1

Una referencia de C++ no es una referencia en el sentido en que la mayoría de los otros idiomas usan el término; es más como un alias. El uso de una referencia en C++ no implica "desreferenciarlo" de la misma manera que desreferencia un puntero; efectivamente es el objeto asignado.

No existe realmente un objeto nulo instancia, por lo que no puede crear una referencia en C++ a tal cosa. En otros lenguajes, una referencia nula es el equivalente de un puntero nulo C++; en realidad no contiene nada.

Ahora, con respecto a sus otros pensamientos: 1. tener referencias que no admiten nulos es una buena cosa en mi mente; significa que obtienes todos los beneficios de pasar por referencia sin ninguno de los requisitos para verificar nulos en cualquier lugar. 2. Las referencias anulables no reemplazan a los punteros ... si necesita hacer memoria o IO funcionan a un nivel bajo, va a querer acceso sin formato a la memoria y dispositivos mapeados en la memoria. Puede echarle un vistazo a C# (o C++/CLR), que tiene referencias administradas y punteros no administrados precisamente por esta razón.

Cuestiones relacionadas