我将用代码来说明我的问题:
#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;
}
当我运行此代码(在 VS2008 中)时,我得到以下信息:错误 C2664: 'PrintInt' : 无法将参数 1 从 'unsigned char *' 转换为 'const unsigned char *&'。如果我取消注释“const”注释,它就可以正常工作。
但是指针不应该隐式转换为 const 指针然后引用吗?我期望这能起作用是错误的吗?谢谢!
如果按照您的建议将指针转换为 const 指针,则该转换的结果是一个临时值,即rvalue。不能将非常量引用附加到右值 - 这在 C++ 中是非法的。
例如,由于类似的原因,此代码将无法编译
int i = 42;
double &r = i;
即使类型
int
可以转换为类型 double
,但这仍然并不意味着您可以将 double &
引用附加到该转换的结果。
但是,const 引用(即对 const 类型的引用)可以附加到右值,这意味着该代码将完美编译
int i = 42;
const double &r = i;
在您的情况下,如果您将函数声明为
void PrintInt(const unsigned char* const& ptr) // note the extra `const`
代码将编译。
这将打破常量正确性:
// 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; // !!!!
如果允许转换,上面的代码将编译。一旦你用
cp
(该语言禁止)初始化 p
,它们就是别名。现在您可以使用 cp
指向任何常量对象,因为它是指向 constant 对象的指针。修改 p
指向的值也是有效的代码,因为它是指向非常量对象的指针,但由于 p
和 cp
相同,因此将修改常量。
我想你需要:
void PrintInt(const unsigned char* const& ptr)
如果你想通过引用传递 const 指针。
不能将引用转换为指针,因为指针可以为空,而引用则不能。换句话说,引用比指针更具限制性。引用始终是有效的指针,但相反的指针并不总是正确。