2010-05-25 17 views
8

będę zilustrować moje pytanie o kodzie:dlaczego nie niejawna konwersja z wskaźnikiem odniesienia do const wskaźnik

#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; 
} 

Kiedy uruchomić ten kod (w VS2008) otrzymuję to: błąd C2664: „PrintInt”: nie można przekonwertować parametru 1 z "unsigned char *" na "const unsigned char * &". Jeśli odkomentuję komentarz "const", to działa dobrze.

Jednak nie należy wskaźnik niejawnie przekształcić w wskaźnik const, a następnie odwołać się? Czy jestem w błędzie, oczekując, że to zadziała? Dzięki!

Odpowiedz

10

Jeśli wskaźnik zostanie przekonwertowany na wskaźnik const, zgodnie z sugestią, wówczas wynikiem tej konwersji jest wartość tymczasowa, rvalue. Nie można dołączyć nie-const odniesienia do wartości r - jest to nielegalne w C++.

Na przykład, ten kod nie zostanie skompilowany z podobnego powodu

int i = 42; 
double &r = i; 

Chociaż typ int jest zamienny wpisać double, to jeszcze nie znaczy, że można dołączyć double & odniesienie do wyniku ta konwersja.

Jednak const odniesienia (tj odwołaniem odniesienia do const typu) mogą być dołączone do rvalue, co oznacza, że ​​ten kod zostanie skompilowany perfekcyjnie

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

W twoim przypadku, jeśli zadeklarować działa jako

kod zostanie skompilowany.

+0

Tak, co powiedział :) Sygnatura funkcji potrzebuje referencji stałej: choć przekazywanie wskaźników przez odniesienie jest trochę bezcelowe, ponieważ wskaźniki i odniesienia muszą i tak być tej samej wielkości ... – James

+0

To nie jest poprawne. Odniesienia są bardziej prawdopodobne, że mają rozmiar zerowy niż ten sam rozmiar co wskaźniki. – Asher

0

myślę, że trzeba:

void PrintInt(const unsigned char* const& ptr)

jeśli chcesz przekazać const wskaźnika przez odniesienie.

+1

Jaki jest sens przekazywania wskaźnika przez odniesienie do const? Dlaczego po prostu nie przekazać wskaźnika przez wartość? – fredoverflow

+0

@Fred Dokładnie, nie zawracałbym sobie głowy; zobacz mój komentarz @AndreyT :) – James

7

To złamie const-poprawności:

// 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;    // !!!! 

Jeśli konwersja pozwolono powyższy kod będzie kompilować. Po zainicjowaniu cp z p (zabronione w tym języku) są one aliasami. Teraz możesz użyć parametru cp, aby wskazać dowolny stały obiekt, ponieważ jest to wskaźnik do obiektu o stałej wartości . Modyfikowanie wartości wskazanej przez p jest również prawidłowym kodem, ponieważ jest wskaźnikiem do obiektu nie będącego stałym obiektem, ale ponieważ p i cp są takie same, to modyfikowałby stałą.

0

Nie można przekonwertować odwołania do wskaźnika, ponieważ wskaźnik może mieć wartość null, a odwołanie nie. Innymi słowy, odniesienie jest bardziej restrykcyjne niż wskaźnik. Odwołanie jest zawsze poprawnym wskaźnikiem, ale przeciwieństwo nie zawsze jest prawdziwe.

Powiązane problemy