views:

164

answers:

3

I'll illustrate my question with code:

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

When I run this code (in VS2008) I get this: error C2664: 'PrintInt' : cannot convert parameter 1 from 'unsigned char *' to 'const unsigned char *&'. If I uncomment the "const" comment it works fine.

However shouldn't pointer implicitly convert into const pointer and then reference be taken? Am I wrong in expecting this to work? Thanks!

A: 

I think you need:

void PrintInt(const unsigned char* const& ptr)

if you want to pass a const pointer by reference.

Autopulated
What is the point of passing a pointer by reference-to-const? Why not just pass the pointer by value?
FredOverflow
@Fred Exactly, I wouldn't bother; see my comment @AndreyT :)
Autopulated
+3  A: 

If the pointer gets converted to a const pointer, as you suggest, then the result of that conversion is a temporary value, an rvalue. You cannot attach a non-const reference to an rvalue - it is illegal in C++.

For example, this code will not compile for a similar reason

int i = 42;
double &r = i;

Even though type int is convertible to type double, it still doesn't mean that you can attach a double & reference to the result of that conversion.

However, a const reference (i.e. a reference of reference-to-const type) can be attached to an rvalue, meaning that this code will compile perfectly fine

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

In your case if you declare your function as

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

the code will compile.

AndreyT
Yeah, what he said :) function signature needs a const reference: though passing pointers by reference is a bit pointless since pointers and references need to be the same size anyway...
Autopulated
+3  A: 

That will break the const-correctness:

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

If the conversion was allowed the above code would compile. Once you have initialized cp with p (forbidden in the language) they are aliases. Now you can use cp to point to any constant object, since it is a pointer to a constant object. Modifying the value pointed by p is also valid code, since it is a pointer to a non-const object, but since p and cp are the same it would be modifying a constant.

David Rodríguez - dribeas