假设有一个函数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;
}
此问题是否有任何已知名称?另外,有什么方法可以警告编译器要小心吗?
答案 0 :(得分:5)
这段代码定义明确,没有问题。
代码const int &b
表示:
b
指的是int
b
不得用于修改int
。然而,通过其他方式修改int
完全没问题。例如,通过此处a
。在编译f
时,编译器必须考虑a
和b
可能都引用同一个对象。
某些编译器具有扩展,以指定函数参数(或其他变量)不应该别名;例如在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
的整数值在生成输出之前递增。)但是,根据编译器和选项,可以区别对待这种别名。在一般情况下,其行为可能未定义。