Pai*_*ait 11 c++ rvalue ternary c++11
如果使用C++ 11编译器编译此程序,则向量不会移出函数.
#include <vector>
using namespace std;
vector<int> create(bool cond) {
vector<int> a(1);
vector<int> b(2);
return cond ? a : b;
}
int main() {
vector<int> v = create(true);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果您返回这样的实例,则会移动它.
if(cond) return a;
else return b;
Run Code Online (Sandbox Code Playgroud)
我用gcc 4.7.0和MSVC10试了一下.两者的行为方式相同.
我猜这种情况发生的原因是:
三元运算符类型是一个左值,因为它在执行return语句之前被计算.此时a和b还不是xvalues(即将到期).
这个解释是否正确?
这是标准中的缺陷吗?
在我看来,这显然不是预期的行为和非常常见的情况.
这将解决它
return cond ? std::move(a) : std::move(b);
Run Code Online (Sandbox Code Playgroud)
将三元运算符视为函数,就像代码一样
return ternary(cond, a, b);
Run Code Online (Sandbox Code Playgroud)
参数不会隐式移动,您需要将其显式化.
以下是相关的标准报价:
12.8第32段:
在下列情况下允许复制省略 [...]
- 在
return具有类返回类型的函数的语句中,当表达式是具有与函数返回类型相同的cv-unqualified类型的非易失性自动对象(除函数或catch子句参数之外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作- [当
throw有条件的时候]- [当来源是临时的,有条件的时候]
- [
catch按价值计算,有条件]
第33段:
当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值.[ 注意:无论是否发生复制省略,都必须执行此两阶段重载决策.如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数.- 结束说明 ]
由于表达式return (cond ? a : b);不是简单的变量名,因此不适用于复制省略或右值处理.也许有点不幸,但很容易想象一下这个例子稍微进一步扩展,直到你为编译器实现带来期待.
当然,std::move当您知道它是安全的时,您可以明确地告诉返回值,从而解决所有这些问题.
| 归档时间: |
|
| 查看次数: |
607 次 |
| 最近记录: |