为什么我不能将非const指针传递给以指向const的指针作为其参数的函数 [英] Why cant I pass a non const pointer to a function taking a reference to a pointer to a const as its argument

查看:277
本文介绍了为什么我不能将非const指针传递给以指向const的指针作为其参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Here's a code snippet that hopefully conveys what I'm trying to do:

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*&)’

推荐答案

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

Supposing that you could do it, you could write the following:

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-cast(或等效常量),否则无法尝试修改const对象.因此,编译器必须拒绝此代码.禁止const int*&绑定到int*是上面代码中唯一让编译器拒绝的地方:每隔一行都可以.

The purpose of const is to ensure that user code cannot attempt to modify a const object unless it contains a const-cast (or equivalent). So the compiler has to refuse this code. Forbidding a const int*& from binding to an int* is the only place in the code above that's reasonable for the compiler to refuse: every other line is fine.

这是您不能将int**隐式转换为const int **的相同原因.

It's the same reason you can't implicitly convert int** to const int **.

除了基于const安全性的动机外,您还可以考虑如果int*const int*是不同类型,那么恰好可以转换为它.同样,您可以将int转换为double,但是double&不能绑定到int左值.这不是全部原因,因为实际上int*const int*具有相同的大小和表示形式,而intdouble没有.因此,如果不是因为它会破坏const系统,可能会有一种特殊情况允许它.

Aside from the motivation in terms of const-safety, you can think if it in terms of int* being a different type from const int*, that just so happens to be convertible to it. Likewise, you can convert int to double, but a double& can't bind to an int lvalue. That's not the full reason, because actually int* and const int* have the same size and representation, whereas int and double don't. So there could be a special-case to allow it if not for the fact that it would break the const system.

C ++对strchr同时具有const和非const重载的原因与此问题有关:您的函数updatePointer修改其输入而不是返回更新后的值,但是原理相似. C风格的单个strchr允许您将指针指向const的清洗"到指针指向非const的对象而无需强制转换,这是const系统中的一个漏洞. C ++(a)具有重载,(b)具有比C更严格的类型系统,因此它可以解决该问题.

The reason that C++ has both const and non-const overloads for strchr is related to this issue: your function updatePointer modifies its input rather than returning the updated value, but the principle is similar. The C-style single strchr allows you to "launder" a pointer-to-const into a pointer-to-non-const without a cast, and it's a hole in the const system. C++ (a) has overloading and (b) has a stricter type system than C, so it closes that hole.

如果您想让实函数updatePointerstrchr一样工作-检查指向的数据并计算指针的新值,那么您将处于与strchr相同的情况.这与新值无关(对于strchr,请返回,对于updatePointer则将其写回),因为问题是您希望新指针具有相同的const限定符.作为输入.您需要提供const和非const重载或函数模板.

If you want your real function updatePointer to work like strchr -- examine the data pointed to and compute a new value for the pointer, then you're in the same situation that strchr is. That's regardless of what it does with the new value (return it in the case of strchr, write it back in the case of updatePointer), because the issue is that you want the new pointer to have the same const-qualification as the input. You need to provide either const- and non-const overloads or a function template.

如果只需要使用实函数updatePointer将指针移动一定距离,无论所指向的数据如何,都可以使用std::advance.

If you only need your real function updatePointer to move a pointer by a certain distance, regardless of the data pointed to, you could use std::advance instead.

这篇关于为什么我不能将非const指针传递给以指向const的指针作为其参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆