移动语义在哪里是有益的好例子

Good example of where move semantics would be beneficial

本文关键字:语义 在哪里 移动      更新时间:2023-10-16

EDIT:我希望下面的代码速度慢(并进行过多的复制),这样我就可以使用移动语义重写它,并比较这两种方法

我在一个类中有以下代码:

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对象复制构造函数

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的应用?

一个选项可以是:

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,并强制编译器复制返回的列表。

如果你只想演示移动语义提供的加速,你可以使用这样一种情况,即你实际上不必为了它的有用而与编译器斗争,比如在其范围内移动自动作用域集合时,比如:

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字符串的move构造函数中交换,速度更快。