在C ++标准(N4618,$ 17.5.4.9,[res.on.argument],(1.3))中,可以说实现是免费的,不对rvalue引用执行别名检查:
如果函数参数绑定到右值引用参数,则实现可以假设 此参数是对此参数的唯一引用。 [ 注意: 如果参数是通用参数 形式 T&安培;&安培; 和一个类型的左值 一个 绑定,参数绑定到左值引用(14.8.2.1) 因此不在前一句中。 - 结束说明 ] [[ 注意: 如果程序转换左值 将该左值传递给库函数时的xvalue(例如,通过使用参数调用该函数) 的std ::移动(X) ),该程序有效地要求该函数将该左值作为临时值处理。 实现可以自由地优化别名检查,如果参数可能需要这些检查 是一个左值。 - 结束说明 ]
我希望将这样的假设应用于整个翻译单元。例如,函数f
:
class A{
int a;
//....
};
int f(A&& r1,A&& r2){
r1.a=10;
r2.a=3;
return r1.a;
}
生成以下程序集:
movl $10, (%rdi)
movl $3, (%rsi)
movl (%rdi), %eax
retq
如果返回值是r1.a
的加载,因为编译器会考虑f
可能以这种方式调用:f(move(an_A),move(an_A))
现在,如果我将其中一个参数声明为限制:
int f(A&& __restrict__ r1,A&& r2){
r1.a=10;
r2.a=3;
return r1.a;
}
我们得到以下程序集:
movl $10, (%rdi)
movl $3, (%rsi)
movl $10, %eax
retq
在这种情况下,我们告诉编译器假设参数r1
和r2
永远不会绑定到同一个对象。因此它直接返回a.a
中存储的值。
对于任何采用右值参考参数的库函数,这正是C ++标准所允许的那种优化。
我相信在大多数(如果不是全部)真实案例程序中,像f(move(an_A),move(an_A))
这样的调用肯定会导致“无证件行为”,因为作为程序员,我永远不会指望用户传递两个有效的参数参数同一个对象。
所以我几乎没有问题:
f(move(an_A),move(an_A))
这样的调用发生了,所以在实施f
时,程序员必须处理这个调用案例吗?