c ++将单个变量作为引用和const引用传递

时间:2016-04-16 03:24:37

标签: c++

假设有一个函数f,它通过引用接收两个变量,另一个是常量引用。

如果我将单个变量作为两个参数传递,则会发生错误:

结果:

a: 6
b: 6

void f(int &a,const int &b)
{
    a=a+1;
    std::cout<<"a: "<<a<<"\n";
    std::cout<<"b: "<<b<<"\n";
}

int main()
{
    int m=5;
    f(m,m);
    return 0;
}

此问题是否有任何已知名称?另外,有什么方法可以警告编译器要小心吗?

2 个答案:

答案 0 :(得分:5)

这段代码定义明确,没有问题。

代码const int &b表示:

  • b指的是int
  • 表达式b不得用于修改int

然而,通过其他方式修改int完全没问题。例如,通过此处a。在编译f时,编译器必须考虑ab可能都引用同一个对象。

某些编译器具有扩展,以指定函数参数(或其他变量)不应该别名;例如在MSVC ++ 2015中,您可以写:

void f(int & __restrict a, const int & __restrict b)

然后编译器可以编译f,假设&a != &b,即它可能为您的代码输出6 5,现在这将是静默未定义的行为 - 编译器不是必需的诊断违反__restrict

的行为

当编写一个具有相同类型(不包括资格)或char的多个引用或指针参数的函数时,您必须意识到某些参数可能会对其他参数进行别名。您可以通过以下方式之一提交:

  • 编写代码,使其即使参数别名
  • 也能正常工作
  • 加入if ( &a == &b ) return;
  • 等支票
  • 使用__restrict并记录调用者的onus是否为别名。

这显示的一个常见情况是类的重载operator=。此函数需要支持写x = x;的人,即*this可以为函数参数设置别名。有时人们通过检查if ( &a == this ) return;来解决这个问题,有时他们会省略该检查,但设计实现以便即使它们相同也能正常工作。

答案 1 :(得分:3)

这似乎正常工作&#34;。

您已定义该函数采用两个参数。声明第一个参数表示可以在a中更改引用的整数f(),但不应更改b

这两个参数都是通过引用传递的,并且您违反了const的使用,因为更改的a也被引用为b

这种行为是我没有优化的期望。 (实际存储为m的整数值在生成输出之前递增。)但是,根据编译器和选项,可以区别对待这种别名。在一般情况下,其行为可能未定义。