coi*_*ung 4 c++ pass-by-reference lvalue auto c++11
class Obj {
public:
Obj(int aa, int bb): a(aa), b(bb) {}
Obj(const Obj& o) {a = o.a; b = o.b;std::cout << "copying" << std::endl;}
Obj(Obj&& o) {a = o.a; b = o.b;std::cout << "moving" << std::endl;}
int a;
int b;
};
const Obj& Min(const Obj &o1, const Obj &o2) {
if (o1.a > o2.a) {
return o1;
} else {
return o2;
}
}
int main() {
using namespace std;
auto o1 = Obj(1,1);
auto o2 = Obj(2,2);
auto res = Min(o1, o2);
cout << res.a << endl;
res.a = 100;
cout << o1.a << endl;
cout << o2.a << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
程序仍会打印一个单词copying,表示复制构造函数已激活.那么构造函数在哪里?为什么函数不返回引用,o1以便修改值res也会改变值o1?
副本在声明中完成:
auto res = Min(o1, o2);
Run Code Online (Sandbox Code Playgroud)
Min()返回类型是const Obj&.在auto上述将被推断为Obj,不const Obj&(即,res类型将是Obj).res,它是一个对象,通过复制构造函数(即Obj::Obj(const Obj&))初始化,因此发生了复制结构.
如果你改写:
auto& res = Min(o1, o2)
Run Code Online (Sandbox Code Playgroud)
res将是类型,const Obj&并且不会在那里进行复制构造,因为res它将是引用,而不是对象.
这与auto推断类型的方式有关:
从CPP工作草案(N4713):
10.1.7.4.1占位符类型推导[dcl.type.auto.deduct]
...
4.如果占位符是自动类型说明符,则使用模板参数推导的规则确定推断类型T'替换T.
和:
17.9.2.1从函数调用中减去模板参数[temp.deduct.call]
...
2.如果P不是引用类型:
...
(2.3) - 如果A是cv限定类型,则顶级类型推导忽略了A类型的cv限定符.
- 如果P是引用类型,则P引用的类型用于类型推导.
所以auto在下面的声明中
auto res = Min(o1, o2);
Run Code Online (Sandbox Code Playgroud)
推导res作为Obj由此进行的分配拷贝构造函数.
所以修改上面这个:
auto& res = Min(o1, o2);
Run Code Online (Sandbox Code Playgroud)
将能够auto演绎res为const Obj&.
但是如果你这样做,res不能在main中进行修改,因为它是一个const参考