通过非常量引用参数修改常量引用参数

Gab*_*e B 34 c++ const-correctness pass-by-reference pass-by-const-reference

考虑以下代码:

#include <iostream>

void f(int const& a, int& b)
{
  b = a+1;
}

int main() {
  int c=2;
  f(c,c);
  std::cout << c << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
  • 函数f采用两个引用参数:int const& aint& b。因此,f不应该修改a,但它可以修改b,并且确实可以。
  • 但是,在 中main,我传递了相同的变量,同时引用bya和 by b。作为f修改b,它也修改a,它应该不应该

此代码在没有任何警告的情况下编译并打印3。如果我们单独跟踪每个变量,它看起来像常量-正确性推崇:c是非const,因此它是完全没有把它作为一个const参考的a,也可作为一个非const REF为b,和体内f我们modify b,这是非常量,而不是 touching a,这是const。但是,当c同时使用 asa和 as 时ba会在 的主体内进行修改f,这违反了aconst的假设,即使const_cast从未调用过显式。

我尽可能地简化了这个例子,但是人们很容易想到不那么明显的用例(例如const作用于非常量引用参数的方法)。

我的问题是:

  • 我们真的可以说上面的代码是常量正确的吗?
  • 上述用例是已知模式吗?这被认为是不好的做法吗?
  • 除了让读者感到困惑之外,上面的代码还能成为技术问题的根源吗?例如未定义的行为,或者编译器执行错误的简化假设?

Nat*_*ica 30

但是,在 中main,我传递了相同的变量,同时引用了 bya和 by b。作为f修改b,它也修改a,它应该不应该

f修改b所指的内容时,它不会修改a. 它修改了a引用的内容,但没关系,因为b不是const。只有当您尝试a通过使用来修改所引用的内容时,您才会遇到a问题。

我们真的可以说上面的代码是常量正确的吗?

是的。您不修改 const 变量。

除了让读者感到困惑之外,上面的代码还能成为技术问题的根源吗?例如未定义的行为,或者编译器执行错误的简化假设?

不,您的代码是合法的,并且会在所有符合标准的编译器上产生相同的结果。


一个常量引用参数const如果不是const开始的,就不会成为它所引用的东西。它所做的一切都会阻止您使用引用来修改对象。另一个指向该对象的指针或引用仍然可以改变它,只要它不是const它自己。


jvd*_*jvd 7

是的,代码是常量正确的,不,这个特定的代码没有未定义的行为。你在这里写的是引用别名的一个简单案例,它归结为引擎盖下的指针别名

话虽如此,像这样的别名通常是不可取的,因为对于程序员和编译器来说,它确实更复杂。此外,这会阻止某些优化,尤其是处理内存块。