2010-02-24 6 views
5

¿No es un puntero solo una referencia cuando no lo quita?¿No es un puntero solo una referencia cuando no lo desreferencia?

#include "stdafx.h" 
#define BOOST_TEST_MODULE example 
#include <boost/test/included/unit_test.hpp> 


std::list<int>* user_defined_func() { 
    std::cout << "BEGIN: user_defined_func" << std::endl; 
    std::list<int>* l = new std::list<int>; 

    l->push_back(8); 
    l->push_back(0); 

    std::cout << "END: user_defined_func" << std::endl; 

    return l; 
} 


bool validate_list(std::list<int> &L1) 
{ 

    std::cout << "BEGIN: validate_list" << std::endl; 

    std::list<int>::iterator it1 = L1.begin(); 

    for(; it1 != L1.end(); ++it1) 
    { 
     if(*it1<= 1){ 

     std::cout << "Validation failed because an item in the list was less than or equal to 1." << std::endl; 
     std::cout << "END: validate_list" << std::endl; 
     return false; 
     } 
    } 

    std::cout << "Test passed because all of the items in the list were greater than or equal to 1" << std::endl; 
    std::cout << "END: validate_list" << std::endl; 
    return true; 
} 

BOOST_AUTO_TEST_SUITE(test) 
BOOST_AUTO_TEST_CASE(test) 
{ 
    std::list<int>* list1 = user_defined_func(); 
    BOOST_CHECK_PREDICATE(validate_list, (list1)); 
} 
BOOST_AUTO_TEST_SUITE_END() 

En la línea,

BOOST_CHECK_PREDICATE(validate_list, (list1)); 

anterior, me dijeron que no puedo dejar pasar puntero a la función que espera referencia. Pensé que un puntero (que no ha sido desreferenciado) era solo una dirección (es decir, una referencia). ¿Que me estoy perdiendo aqui?

Respuesta

4

¿No es un puntero solo una referencia cuando no lo des-referencia?

No, un puntero contiene un valor que se interpreta como una dirección de memoria. (Si contiene un valor que es realmente una dirección de memoria válida es otra pregunta)

Una referencia es un alias, otra forma de referirse a un valor existente.

int i = 5; 
int* p = &i; // The value in p is the address that i is stored at. 
int& r = i; // The value in r is 5, because r is an alias of i. 
      // Whenever you use r, it's as if you typed i, and vice versa. 
      // (In this scope, anyway). 

int sum = i + r; // Identical to i + i or r + i or r + r. 

Editar:

desde lista1 es un puntero, ¿Cómo accedo a la referencia ...?

Tiene dos opciones. Puede derefence el puntero para obtener la lista al que apunta:

std::list<int>* list1 = user_defined_func(); 
std::list<int>& list1ref = *list1; 
BOOST_CHECK_PREDICATE(validate_list, list1ref); 
delete list1; 

Por supuesto, esto podría reducirse a:

std::list<int>* list1 = user_defined_func(); 
BOOST_CHECK_PREDICATE(validate_list, *list1); 
delete list1; 

Su función de validación podría tomar un puntero en lugar de una referencia (recordemos para cambiar L1 {algo} a L1 -> {algo}):.

bool validate_list(std::list<int>* L1) { ... } 
+0

de user_defined_func() Devuelvo un puntero a una lista que ha creado. Así que este puntero se devuelve a la variable de puntero list1 en BOOST_AUTO_TEST_CASE Ahora que la lista1 es un puntero, ¿cómo accedo a la referencia del (objeto?) Al que apunta el puntero list1? – leeand00

+1

@ leeand00: Buena pregunta. He editado mi publicación con mi respuesta. – Bill

+0

Bien, necesitaba cambiar mi función validate_list para que tomara un puntero en lugar de una referencia. Eso lo aclaró. Ha pasado un tiempo desde que hice C++ y no recordaba o no estaba seguro de que hubiera una diferencia entre una referencia y un puntero no desreferenciado. – leeand00

6

Lo tiene al revés: las referencias se pueden implementar usando punteros (aunque normalmente no debería pensar en eso), pero los punteros en C++ no son referencias. Puede estar confundido porque en C, pasar cosas usando punteros se llama "llamar por referencia", pero eso se debe a que C no tiene referencias reales como lo hace C++.

+0

Y la razón de la downvote era .... –

+1

Usted fuerza' dar ninguna explicación adicional. Solo decir que los punteros no son referencias no es suficiente, el OP ya lo vio. Probablemente esperaba una explicación de "cómo" y "por qué". –

+1

@Pop Si vamos a comenzar a votar negativamente las respuestas que no cumplen exactamente las expectativas de los usuarios individuales, a pocos de nosotros nos quedará alguna representación. Este es un sitio web técnico, y los votos abajo deben reservarse para errores técnicos. –

1

Si bien las referencias generalmente se implementan como punteros bajo el capó, el lenguaje las trata como dos conceptos separados. Hay algunas diferencias importantes entre los dos:

  1. Las referencias deben estar enlazados en tiempo de inicialización y no pueden ser re-unían para hacer referencia a un objeto diferente, mientras que los punteros pueden apuntar a diferentes direcciones en diferentes momentos.
  2. Los punteros pueden ser NULL, pero las referencias siempre deben vincularse a un objeto.
2

Yo diría que una referencia es más como un puntero manejado por el compilador.

Con un puntero regular tiene control total sobre la referencia, puede reasignarla, eliminarla, invertir algunos bits ... lo que sea.

Con una referencia, el compilador maneja el puntero y le dan un objeto que no tiene que quitar la referencia, pero sigue siendo un puntero al mismo objeto.

para hacer su trabajo de código que tendría que hacer

BOOST_CHECK_PREDICATE(validate_list, (*list1)); 

pero estoy seguro de que ya lo sabía :)

creo que esta pregunta y la respuesta es la misma línea What are the differences between a pointer variable and a reference variable in C++?

+0

@Charles Eso no soluciona el código en mi publicación anterior. Ya lo he intentado. – leeand00

+0

@Charles Estoy usando Visual Studio 2005, ¿tiene algo que ver con eso? – leeand00

+0

hmm, bueno, es una macro de prueba de refuerzo, tal vez hay una función de utilidad de impulso especial que necesita utilizar para desreferenciar el puntero – Charles

13

Los punteros y las referencias son similares, pero diferentes en varios aspectos:

  1. Tienen una sintaxis de acceso diferente. Si tiene T* a y T& b, tiene acceso a las variables y funciones del miembro usando a->member y b.member respectivamente.
  2. Los punteros no apuntan a nada, mientras que las referencias siempre deben apuntar a algo. a = 0 es legal, pero no es b = 0 ni nada por el estilo.
  3. Los punteros se pueden "volver a insertar" (es decir, el punto se puede cambiar) mientras que las referencias no. a = &b es legal, pero int c; b = c; no es (T& b = c es, sin embargo, las referencias solo pueden establecerse en su inicialización). (Gracias Mike D.)
  4. Los punteros no pueden hacer referencia a los temporales, pero las referencias const sí.
  5. Los punteros pueden señalar a otros punteros, (T**) pero las referencias no pueden hacer referencia a otras referencias (es decir, no existe T&&, aunque tenga en cuenta que C++ 0x usará T&& para definir la semántica de movimiento). Como resultado, no puede tener matrices de referencias. (Gracias AshleysBrain)

Uno podría preguntarse por qué tenemos referencias, y no solo usar punteros todo el tiempo (como en C). La razón es debido a la sobrecarga del operador o ciertos operadores.

Considere el operador de asignación. ¿Cuál sería la sintaxis de la función sin referencias? Si se tratara de T* operator=(T* lhs, T rhs) entonces tendríamos que escribir cosas como:

int a(1); 
&a = 2; 

Esencialmente, las referencias nos permiten tener funciones de L-valores, sin la necesidad de una referencia de puntero y la sintaxis eliminar la referencia.

+2

En realidad, 'b = * a' es perfectamente legal, pero realiza una copia y no vuelve a cerrarse la referencia. En cuanto a 'operator = (T * lhs, T rhs)', el compilador podría ocultar el '& a' por usted (solo en el caso de sobrecargas del operador, ya que no habría otra manera de llamar a un operador sobrecargado), pero el la definición se vería rara, con un código como 'lhs-> foo = rhs.foo;'. (Algunos estándares de codificación exigirían un bloque 'if (! Lhs) {handle error}', también.) Feo por todos lados. Personalmente, me gustan los refs porque se comunican con otros desarrolladores que no me estoy volviendo a instalar. –

+0

+1 a Mike D, pero no hay voto para esta respuesta hasta que 'b = * a' se describa correctamente! –

+0

Solo una advertencia, mientras 'T & b = 0' no es posible,' T & b = * ((T *) 0) 'es;) ¡Además, las referencias pueden estar colgando! Todavía no entiendo por qué se decidió que habría 2 estilos de invocaciones ('.' y' -> ') ¡mientras que uno parecía perfectamente suficiente! –

Cuestiones relacionadas