【问题标题】:Why cant I pass a non const pointer to a function taking a reference to a pointer to a const as its argument为什么我不能将非 const 指针传递给一个函数,该函数将指向 const 的指针的引用作为其参数
【发布时间】:2012-09-26 10:53:21
【问题描述】:

这是一个代码 sn-p,希望能传达我想要做的事情:

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

【问题讨论】:

  • 我认为你根本无法获得对 const 的非 const 引用
  • 我决定删除我的答案,因为我不确定你在问什么。
  • 我基本上是在问为什么上面的代码编译不出来
  • 问题很明确,在标题中。但是,该示例并未反映问题......并且该函数的主体显然违反了 OP 想要实现的目标。老实说,这个问题是以一种愚蠢的方式提出的。更重要的是,如果您问为什么代码无法编译。如果您更正示例以反映您的问题,由于完全不同的问题,它仍然无法编译。 =)
  • 我不同意 - 我想要一个可以修改指针但不能修改指针指向的函数。

标签: c++ pointers reference constants


【解决方案1】:

假设你能做到,你可以这样写:

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* 具有相同的大小和表示,而intdouble 则没有。所以如果不是因为它会破坏 const 系统,可能会有一个特殊情况允许它。

C++ 对strchr 有 const 和 non-const 重载的原因与这个问题有关:你的函数 updatePointer 修改了它的输入而不是返回更新的值,但原理是相似的。 C 风格的单一 strchr 允许您将指向 const 的指针“洗白”为指向非 const 的指针而无需强制转换,这是 const 系统中的一个漏洞。 C++ (a) 具有重载,并且 (b) 具有比 C 更严格的类型系统,因此它填补了这个漏洞。

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

如果您只需要真正的函数updatePointer 将指针移动一定距离,无论指向什么数据,您都可以改用std::advance

【讨论】:

    【解决方案2】:

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

    updatePointer(int* const & i);
    

    但是这没有多大意义。传递对指针的引用似乎意味着您打算修改指针,但您不能这样做,因为它被声明为 const。实际上,您只需像中一样传递指针即可获得相同的效果

    updatePointer(int* i);
    

    【讨论】:

    • 对不起,我在问题标题中写错了,在您发布之前没有机会更新
    【解决方案3】:

    Found this 复制到这里以防将来链接中断:

    这个推理有点难以理解。主要问题是: 既然“const int&”可以绑定到“int”,为什么“const int*&”不能绑定到“int*”呢?

    基本上,一旦添加了间接级别(指针),规则就会改变。仅使用一个间接级别(如在单个 * 中),该规则可以表述为:

    对指向 cv 限定类型的指针的引用可以绑定到任何 cv 限定小于或等于指针(即引用)的相同类型。 (多读几遍。)

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

    【讨论】:

      猜你喜欢
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2019-08-17
      • 1970-01-01
      • 2021-03-09
      • 2021-05-08
      • 1970-01-01
      相关资源
      最近更新 更多