2010-05-25 18 views
8

Voy a ilustrar mi pregunta con código:qué hay conversión implícita de puntero para hacer referencia a puntero constante

#include <iostream> 

void PrintInt(const unsigned char*& ptr) 
{ 
    int data = 0; 
    ::memcpy(&data, ptr, sizeof(data)); 
    // advance the pointer reference. 
    ptr += sizeof(data); 
    std::cout << std::hex << data << " " << std::endl; 
} 

int main(int, char**) 
{ 
    unsigned char buffer[] = { 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, }; 

    /* const */ unsigned char* ptr = buffer; 

    PrintInt(ptr); // error C2664: ... 
    PrintInt(ptr); // error C2664: ...  

    return 0; 
} 

Cuando ejecuto el código (en VS2008) me sale esto: error C2664: 'PrintInt': no se puede convertir el parámetro 1 de 'unsigned char *' a 'const unsigned char * &'. Si elimino el comentario "const", funciona bien.

Sin embargo, ¿el puntero no debe convertirse implícitamente en el puntero const y luego debe tomarse la referencia? ¿Estoy equivocado al esperar que esto funcione? ¡Gracias!

Respuesta

10

Si el puntero se convierte en un puntero const, como sugiere, entonces el resultado de esa conversión es un valor temporal, rvalue. No puede adjuntar una referencia no const a un valor r: es ilegal en C++.

Por ejemplo, este código no se compilará por una razón similar

int i = 42; 
double &r = i; 

A pesar de que el tipo int es convertible al tipo double, todavía no quiere decir que se puede adjuntar una referencia double & al resultado de esa conversión.

Sin embargo, una referencia constante (es decir, una referencia de la referencia a const tipo) se puede conectar a un valor de lado derecho, lo que significa que el código se compila perfectamente bien

int i = 42; 
const double &r = i; 

En su caso si usted declara su función como

void PrintInt(const unsigned char* const& ptr) // note the extra `const` 

se compilará el código.

+0

Sí, lo que dijo :) la función signature necesita una referencia constante: aunque pasar punteros por referencia es un poco inútil ya que los punteros y las referencias deben ser del mismo tamaño de todos modos ... – James

+0

Eso no es correcto. Es más probable que las referencias tengan un tamaño cero que el mismo tamaño que los punteros. – Asher

0

creo que es necesario:

void PrintInt(const unsigned char* const& ptr)

si desea pasar un puntero constante por referencia.

+1

¿Cuál es el punto de pasar un puntero por referencia-a-const? ¿Por qué no solo pasar el puntero por valor? – fredoverflow

+0

@Fred Exactamente, no me molestaría; ver mi comentario @AndreyT :) – James

7

que romperá la const-corrección:

// if it was allowed 
const int x = 5; 
int *p; 
const int*& cp = p; // cp is a ´constant´ alias to p 
cp = &x;   // make cp (and p) point to a constant 
*p = 7;    // !!!! 

Si la conversión se permitió que el código anterior podría compilar. Una vez que haya inicializado cp con p (prohibido en el idioma) son alias. Ahora puede usar cp para apuntar a cualquier objeto constante, ya que es un puntero a un objeto constante. La modificación del valor apuntado por p también es un código válido, ya que es un puntero a un objeto no const, pero dado que p y son lo mismo, estaría modificando una constante.

0

No se puede convertir una referencia a un puntero porque el puntero puede ser nulo y una referencia no. En otras palabras, la referencia es más restrictiva que un puntero. Una referencia es siempre un puntero válido, pero lo opuesto no siempre es cierto.

Cuestiones relacionadas