【问题标题】:How do I prevent a const& argument from being changed indirectly?如何防止 const 参数被间接更改?
【发布时间】:2016-01-07 03:18:20
【问题描述】:

是否有可能使const& 真正不可变?

int* side_effect;
void function(int const& i){
  *side_effect = 123;
}

int main(){

  int i = 0;
  side_effect = &i;

  //based on the function signature, i is suspected not to change.  
  //however, that is not the case.
  function(i);
}

是否有任何编译器警告、属性、编译器扩展或语言功能可以用来避免此类问题?

【问题讨论】:

  • 我们不是最近才有这个问题吗? Here.
  • const & 并不意味着“无法更改”。它的意思是“不能通过这个参数来改变”。
  • 创建一个本地副本,而不是引用其他东西!
  • (M)任何功能都可以被故意破坏。不应像在您的示例中那样使用全局指针。但是,您可以尝试在分配之前进行检查,例如 if(side_effect != &i)
  • 声明const int i = 0;,当您将其地址分配给非常量指针时,编译器肯定会警告您。对您的问题的任何其他可能解释都会导致广泛且有些毫无意义(尽管有指示)的运行时检查。

标签: c++ reference immutability side-effects c++17


【解决方案1】:

如果你想让一个值成为一个真正的常量,你可以将它作为模板值参数传递。

template<int i>
void function(){
  *side_effect = 123;
}

任何操作都无法修改i

这要求输入是编译时常量(并在编译时由编译器验证)。

所以这不起作用:

int main(){
  int i = 0;
  side_effect = &i;

  function<i>();
}

因为i 不是编译时常量。如果我们做到了:

int main(){
  const int i = 0;
  side_effect = &i;

  function<i>();
}

function&lt;i&gt; 行有效,但side_effect = &amp;i 无效。如果我们添加演员表:

int main(){
  const int i = 0;
  side_effect = const_cast<int*>(&i);

  function<i>();
}

现在*side_effect = 123 操作在function 内变为UB。

另一种不需要传入的值是真正的编译时常量的方法是不引用:

void function(int i){
  *side_effect = 123;
}

取而代之的是获取本地副本(intconst int 作为参数,取决于我们是否希望 function 有权修改 i)。

您想要的完整版本——我们参考外部数据,然后确保外部数据保持不变——可以很容易地证明等同于一般情况下的停止问题。

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 2017-08-02
    • 2023-03-28
    • 1970-01-01
    • 2013-06-14
    相关资源
    最近更新 更多