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

时间:2013-11-27 18:48:17

标签: c++ visual-c++ c++11 copy move

编辑:我希望下面的代码很慢(并进行过多的复制),以便我可以使用移动语义重新编写它并比较这两种方法。

我在类中有以下代码:

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

2 个答案:

答案 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字符串的移动构造函数中交换,速度非常快。