c++ rvo vs std::move

c++ rvo vs std::move

To summarize, RVO is a compiler optimization technique, while std::move is just an rvalue cast, which also instructs the compiler that it's eligible to move the object. The price of moving is lower than copying but higher than RVO, so never apply std::move to local objects if they would otherwise be eligible for the RVO.

 

#include <iostream>
#include <chrono>
#include <unordered_map>

class BigObject {
public:
    BigObject() {
        std::cout << "constructor. " << std::endl;
    }
    ~BigObject() {
        std::cout << "destructor."<< std::endl;
    }
    BigObject(const BigObject&) {
        std::cout << "copy constructor." << std::endl;
    }
    BigObject(BigObject&&) {
        std::cout << "move constructor"<< std::endl;
    }
};

struct info
{
    std::string str;
    std::unordered_map <int, std::string> umap;
};

int64_t get_current_time_ns()
{
    std::chrono::nanoseconds ss = std::chrono::high_resolution_clock::now().time_since_epoch();
    int64_t tt = ss.count();
    std::cout<<"current time:"<<tt<<std::endl;
    return tt;
}

std::string get_st_v1()
{
    std::string st;
    st = "ttppppppppppppppppppppppppppppppppppppppppppppppppppppppppp";
    return st;
}

std::string get_st_v2()
{
    std::string st;
    st = "ttppppppppppppppppppppppppppppppppppppppppppppppppppppppppp";
    return std::move(st);
}

info get_info_v1()
{
    info ifo;
    ifo.str = "ttppppppppppppppppppppppppppppppppppppppppppppppppppppppppp";
    ifo.umap.insert(std::make_pair<int, std::string>(6, "eggs"));
    return ifo;
}

info get_info_v2()
{
    info ifo;
    ifo.str = "ttppppppppppppppppppppppppppppppppppppppppppppppppppppppppp";
    ifo.umap.insert(std::make_pair<int, std::string>(6, "eggs"));
    return std::move(ifo);
}

BigObject foo(int n) {

    BigObject localObj;
    return localObj;
}

int main() {
    auto f = foo(1);

    int64_t t_1= get_current_time_ns();

    std::cout<<"test rvo:"<<std::endl;
    for(int i = 0; i< 100000; i++)
    {
        std::string d1 = get_st_v1();
    }

    int64_t t_2= get_current_time_ns();

    std::cout<<"v1 time cost:"<<t_2-t_1<<std::endl;

    std::cout<<"test move:"<<std::endl;
    for(int j = 0; j< 100000; j++)
    {
        std::string d2 = get_st_v2();
    }
    int64_t t_3= get_current_time_ns();

    std::cout<<"v2 time cost:"<<t_3-t_2<<std::endl;

    std::cout<<"info test rvo:"<<std::endl;
    for(int m = 0; m< 100000; m++)
    {
        info d3 = get_info_v1();
    }
    int64_t t_4= get_current_time_ns();

    std::cout<<"info v1 time cost:"<<t_4-t_3<<std::endl;

    std::cout<<"info test move:"<<std::endl;
    for(int n = 0; n< 100000; n++)
    {
        info d4 = get_info_v2();
    }
    int64_t t_5= get_current_time_ns();

    std::cout<<"info v2 time cost:"<<t_5-t_4<<std::endl;

    return 0;
}

 

Result

constructor. 
current time:1568273863513694551
test rvo:
current time:1568273863517139874
v1 time cost:3445323
test move:
current time:1568273863521213442
v2 time cost:4073568
info test rvo:
current time:1568273863574775754
info v1 time cost:53562312
info test move:
current time:1568273863641223923
info v2 time cost:66448169
destructor.

 

Reference

https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/RVO_V_S_std_move?lang=en

https://stackoverflow.com/questions/17473753/c11-return-value-optimization-or-move

https://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion-return-statement

https://stackoverflow.com/questions/12011426/how-to-use-move-semantics-with-stdstring-during-function-return

posted @ 2019-09-12 16:17  SolidMango  阅读(553)  评论(0编辑  收藏  举报