edA*_*a-y 5 c++ language-lawyer
在下面的代码中,我将其step称为成员函数,并将其作为临时值的全局函数.成员函数是允许的,并且有效,而全局函数由于不允许而被禁止invalid initialisation of non-const reference of type ‘kludge&’ from an rvalue of type ‘kludge’.
从语言的角度来看,我试图理解为什么允许一种行为而另一种行为不允许.从技术上讲,调用和函数似乎都是相同的编译,或者至少可以编译.
#include <iostream>
struct kludge {
int a;
kludge() {
a = 1;
}
kludge & step() {
a++;
std::cout << a << ",";
return *this;
}
};
kludge get() {
kludge t;
return t;
}
kludge & step( kludge & t ) {
t.a++;
std::cout << t.a << ",";
return t;
}
int main() {
get().step();
step( get() );
}
Run Code Online (Sandbox Code Playgroud)
您不能将rvalues绑定到非const左值引用1.这适用于step(get())作为step非const左值引用的参数,不能绑定到prvalue(纯rvalue)get().
但是,成员函数本身可以在每个值类别的对象参数上调用,无论是左值还是右值 - [over.match.funcs]/4和/ 5:
对于非静态成员函数,隐式对象参数的类型是
- "左值参考CV
X"为没有声明的函数REF-限定符或与&REF-限定符[..]
对于未使用ref-qualifier声明的非静态成员函数,应用其他规则:
- 即使隐式对象参数不是
const-qualified,也可以将rvalue绑定到参数,只要在所有其他方面,参数可以转换为隐式对象参数的类型. [ 注意:这样的参数是一个rvalue的事实不会影响隐式转换序列的排名(13.3.3.2).- 结束说明 ]
但是,如果使用所谓的ref-qualifiers,则可以限制对特定成员函数有效的值类别.也就是说,如果你写:
kludge & step() & { /* .. */ }
Run Code Online (Sandbox Code Playgroud)
电话会议get().step()也是不正确的.
参考输入" CV1
T1"是通过类型"的表达初始化CV2T2"如下:
- 如果引用是左值引用和初始化表达式
- 是左值[..]
- 有一个类类型(即,
T2是一个类类型),其中T1与引用无关T2,并且可以隐式转换为类型为" cv3T3" 的左值,[...]
- 否则,引用应是对非易失性
const类型的左值引用(即,cv1应为const),或者引用应为右值引用.
临时不能绑定到非常量引用
step( get() );
// ~~~~~ Creates a temporary object (r-value)
// But step( ) excepts a non-const reference
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
523 次 |
| 最近记录: |