编辑:我希望下面的代码很慢(并进行过多的复制),以便我可以使用移动语义重新编写它并比较这两种方法。
我在类中有以下代码:
std::list<boost::shared_ptr<I> > getX(){
std::list<boost::shared_ptr<I> > a;
for(auto kv : b) {
if(something){
a.push_back(kv.second);
}
}
return a;
}
double foo(){
std::list<boost::shared_ptr<I> > a = getX();
现在我在return a
上设置了一个断点,我希望看到正在制作列表的某种副本(std::list
复制构造函数,然后是每个I
对象复制构造函数但是,调试器进入了amdsecgs.asm:
LEAF_ENTRY __security_check_cookie, _TEXT
cmp rcx, __security_cookie ; check cookie value in frame
jne ReportFailure ; if ne, cookie check failure
rol rcx, 16 ; make sure high word is zero
test cx, -1
jne RestoreRcx
db 0f3h ; (encode REP for REP RET)
ret ; no overrun, use REP RET to avoid AMD
; branch prediction flaw after Jcc
我无法看到列表的任何副本。我希望看到列表被复制,然后每个I对象被复制。
(我之所以这样问是因为我正在尝试编写一些代码,这些代码对于使用移动语义进行加速非常有用)。
此代码是否通过返回值优化进行优化?如果是这样,有什么方法可以修改代码以防止RVO被应用?
答案 0 :(得分:0)
一个选项可能是:
std::list<boost::shared_ptr<I> > getX(){
using list = std::list<boost::shared_ptr<I> >;
list empty;
list a;
for(auto kv : b) {
if(something){
a.push_back(kv.second);
}
}
return list( a.empty() ? empty : a );
}
这应该会破坏RVO / NRVO并强制编译器复制返回的列表。
答案 1 :(得分:0)
如果您想要的只是演示移动语义提供的加速,您可以使用一种情况,您实际上不必与编译器对抗以使其有用,例如在其范围内移动自动作用域集合时,像这样:
typedef vector<float> Grades;
unordered_map<int, string> idsToNames;
unordered_map<int, Grades> idsToGrades;
//ids and names being used seperatly
...
//it would now be more useful to merge them
struct StudentInfo {
string mName; Grades mGrades;
StudentInfo(string && name, Grades && grades):mName(name),mGrades(grades){}
};
unordered_map<int, StudentInfo> idsToStudentInfo;
for(pair<int, string>& s : idsToNames) {
idsToStudentInfo.insert(
make_pair(s.first,
StudentInfo(std::move(s.second),std::move(idsToGrades[s.first]))
)
);
}
所以在这里,它们不是复制Grades向量和字符串(char向量),而是在mName字符串和mGrades字符串的移动构造函数中交换,速度非常快。