Clo*_*ees 2 c++ temporary-objects move-constructor c++11
所以,代码第一:
#include <iostream>
#include <utility>
struct X{
int i;
void transform(){}
X() :i(0){std::cout<<"default\n";}
X(const X& src): i(src.i){std::cout<<"copy\n";}
X(X&& msrc) :i(msrc.i){msrc.i=0;std::cout<<"move\n";}
};
X getTransform(const X& src){
X tx(src);
tx.transform();
return tx;
}
int main(){
X x1;// default
X x2(x1); // copy
X x3{std::move(X{})}; // default then move
X x41(getTransform(x2)); // copy in function ,then what?
X x42(std::move(getTransform(x2))); // copy in funciton, then move
X x51( (X()) );//default, then move? or copy?
// extra() for the most vexing problem
X x52(std::move(X())); //default then move
std::cout<<&x41<<"\t"<<&x51<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
然后从cygwin + gcc 4.8.2开始输出C++ 11功能:
default
copy
default
move
copy
copy
move
default
default
move
0x22aa70 0x22aa50
Run Code Online (Sandbox Code Playgroud)
我不太明白的是x41和x51的行.对于x41,是否应该从函数调用返回的临时调用移动构造函数或副本?同样的问题x51.第二个问题是,通过查看输出,x41和x51的结构没有调用任何定义的构造函数,但是对象在它们驻留在内存中时清楚地创建.怎么会这样?
谢谢!
一个未命名的对象自然会&&比const&自然更好.
否则移动语义将无法工作.
现在,对默认/复制/移动构造函数的调用较少,然后人们可能天真地期望,因为有一个允许复制椭圆的特殊规则,而不考虑可观察的行为(否则必须通过优化保留):
12.8复制和移动物体§31
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使该对象的复制/移动构造函数和/或析构函数具有副作用.在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间.在没有优化的情况下销毁.在以下情况下(可以组合以消除多个副本)允许复制/移动操作的省略,称为复制省略:
仍然,如果从函数返回并直接用于初始化对象类型相同,该移动将被省略.
- 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv-unqualified类型的非易失性自动对象(除函数或catch子句参数之外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作.
- 当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过将临时对象直接构造到该对象中来省略复制/移动操作.省略的复制/移动的目标.
- [...还有2个用于异常处理]
所以,浏览你的清单:
X x1;// default
// That's right
X x2(x1); // copy
// Dito
X x3{std::move(X{})}; // default then move
// Yes. Sometimes it does not pay to call `std::move`
X x41(getTransform(x2)); // copy in function ,then what?
// Copy in function, copy to output, move-construction to x41.
// RVO applies => no copy to output, and no dtor call for auto variable in function
// Copy ellision applies => no move-construction nor dtor of temporary in main
// So, only one time copy-ctor left
X x42(std::move(getTransform(x2))); // copy in funciton, then move
// `std::`move` is bad again
X x51( (X()) );//default, then move? or copy? // extra() for the most vexing problem
// Copy-elision applies: default+move+dtor of temporary
// will be optimized to just default
X x52(std::move(X())); //default then move
// And again `std::`move` is a pessimization
Run Code Online (Sandbox Code Playgroud)
我认为使用static_cast可能会避免绑定临时,意味着移动可以被省略,但没有这样的运气:1376.临时到右值参考的static_cast感谢@dyp发掘这个问题.
| 归档时间: |
|
| 查看次数: |
172 次 |
| 最近记录: |