为什么这个程序调用复制构造函数而不是移动构造函数?
class Qwe {
public:
int x=0;
Qwe(int x) : x(x){}
Qwe(const Qwe& q) {
cout<<"copy ctor\n";
}
Qwe(Qwe&& q) {
cout<<"move ctor\n";
}
};
Qwe foo(int x) {
Qwe q=42;
Qwe e=32;
cout<<"return!!!\n";
return q.x > x ? q : e;
}
int main(void)
{
Qwe r = foo(50);
}
Run Code Online (Sandbox Code Playgroud)
结果是:
return!!!
copy ctor
Run Code Online (Sandbox Code Playgroud)
return q.x > x ? q : e;用于禁用nrvo.当我把它包起来时std::move,它确实被移动了.但是在"C++之旅"中,作者说当移动c'tor可用时必须调用它.
我做错了什么?
Sto*_*ica 13
您没有以允许复制/移动省略的方式编写函数.移动取代副本的要求如下:
在以下复制初始化上下文中,可能会使用移动操作而不是复制操作:
- 如果return语句中的表达式是一个(可能带括号的)id-expression,它指定一个对象,该对象具有在body或者最内层封闭函数或lambda-expression的parameter-declaration-clause中声明的自动存储持续时间
首先执行重载决策以选择副本的构造函数,就好像该对象是由rvalue指定的一样.如果第一个重载决策失败或未执行,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值.
以上是C++ 17,但C++ 11的措辞几乎相同.条件运算符不是 id-expression,它在函数范围内命名对象.
一个id表达式就像q或e在你的特定情况下.您需要在该范围内命名对象.条件表达式不符合命名对象的条件,因此它必须预先形成副本.
如果你想在困难的文本墙上练习你的英语理解能力,那么这就是用C++ 11编写的.需要付出一些努力才能看到IMO,但它与上面澄清的版本相同:
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使该对象的复制/移动构造函数和/或析构函数具有副作用.[...]在下列情况下允许复制/移动操作的省略,称为复制省略(可以合并以消除多份副本):
- 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv-unqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作
当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值.
| 归档时间: |
|
| 查看次数: |
1290 次 |
| 最近记录: |