为什么我不能将非const指针传递给一个函数,该函数将一个指向const的指针作为其参数

时间:2012-09-26 10:53:22

标签: c++ pointers reference const

这是一个代码片段,希望传达我正在尝试做的事情:

void updatePointer(const int*& i)
{
  i++;
}

int main() {


  int array[5];
  int* arrayPtr = array;

  updatePointer(arrayPtr );
  return 0;
}

这会给编译器错误:

prog.cpp: In function ‘int main()’:
prog.cpp:16: error: invalid initialization of reference of type ‘const int*&’ from
expression of type ‘int*’
prog.cpp:5: error: in passing argument 1 of ‘void updatePointer(const int*&)’

3 个答案:

答案 0 :(得分:6)

假设您可以这样做,您可以写下以下内容:

const int c = 0;

void updatePointer(const int* &i) {
    i = &c;
}

int main() {
    int *ptr;
    updatePointer(ptr);
    *ptr = 1; // attempt to modify the const object c, undefined behavior
}

const的目的是确保用户代码不能尝试修改const对象,除非它包含const-cast(或等效的)。所以编译器必须拒绝这段代码。禁止const int*&绑定到int*是上面代码中唯一适合编译器拒绝的地方:每隔一行都没问题。

这与您无法将int**隐式转换为const int **的原因相同。

除了const-safety方面的动机之外,您可以认为int*const int*的类型不同,恰好可以转换为int。同样,您可以将double转换为double&,但int无法绑定到int*左值。这不是完整的原因,因为实际上const int*int具有相同的大小和表示,而doublestrchr则没有。因此,如果不是因为它会破坏const系统,可能会有一个特殊情况允许它。

C ++同时具有updatePointer的const和非const重载的原因与此问题有关:函数strchr修改其输入而不是返回更新的值,但原理类似。 C风格的单updatePointer允许你将一个指向const的指针“清洗”到一个没有强制转换的指针到非const,这是const系统中的一个漏洞。 C ++(a)有重载,(b)有一个比C更严格的系统,所以它关闭了那个洞。

如果你希望你的真实函数strchrstrchr一样工作 - 检查指向的数据并为指针计算一个新值,那么你的情况与{{1}相同是的。这与新值的作用无关(在strchr的情况下返回它,在updatePointer的情况下将其写回),因为问题是您希望新指针具有与输入相同的const限定。您需要提供const和非const重载或函数模板。

如果您只需要实际函数updatePointer将指针移动一定距离,无论指向哪个数据,都可以使用std::advance代替。

答案 1 :(得分:5)

你写的是一个引用指向const int的指针的函数。你要求的是

updatePointer(int* const & i);

然而,这没有多大意义。传递对指针的引用似乎意味着您打算修改指针,但是您不能这样做,因为它被声明为const。因为它只是通过传递指针来获得相同的效果,如

updatePointer(int* i);

答案 2 :(得分:1)

Found this 如果以后链接中断,请复制此处:

这个推理有点尴尬。主要问题是: 自从“const int&”可以绑定到“int”,为什么不能“const int *&”被绑定到“int *”?

基本上,一旦添加了间接级别(指针),规则就会改变。只有一个间接级别(如单个*),规则可以表示为:

对指向cv限定类型的指针的引用可以绑定到cv-qualifications小于或等于指针(它是引用)的相同类型的任何类型。 (阅读几次。)

所以“const int *&”的原因不能绑定到“int *”是因为“const int *”和“int *”是两种不同的类型(规则的下划线部分被破坏)。