首页 > 代码库 > c++11 右值引用

c++11 右值引用

http://blog.csdn.net/cpd92/article/details/50651700

http://www.tuicool.com/articles/i2qyyyB

技术分享

move 就是右值引用,减少了copy和释放的过程,提高了程序性能。

#include <iostream>#include <string>#include<vector>using namespace std;class MyString {private:    char* _data;    size_t   _len;    void _init_data(const char *s) {        _data = new char[_len + 1];        memcpy(_data, s, _len);        _data[_len] = \0;    }public:    MyString() {        _data = NULL;        _len = 0;    }    MyString(const char* p) {        _len = strlen(p);        _init_data(p);    }    MyString(const MyString& str) {        _len = str._len;        _init_data(str._data);        std::cout << "Copy Constructor is called! source: " << str._data << std::endl;    }    MyString& operator=(const MyString& str) {        if (this != &str) {            _len = str._len;            _init_data(str._data);        }        std::cout << "Copy Assignment is called! source: " << str._data << std::endl;        return *this;    }    virtual ~MyString() {        if (_data) free(_data);    }};int main() {    MyString a;    a = MyString("Hello");    std::vector<MyString> vec;    vec.push_back(MyString("World"));}

技术分享

在 main 函数中,实现了调用拷贝构造函数的操作和拷贝赋值操作符的操作。MyString(“Hello”) 和 MyString(“World”) 都是临时对象,也就是右值。虽然它们是临时的,但程序仍然调用了拷贝构造和拷贝赋值,造成了没有意义的资源申请和释放的操作。如果能够直接使用临时对象已经申请的资源,既能节省资源,有能节省资源申请和释放的时间。这正是定义转移语义的目的。

 增加转移构造,转移赋值运算符重载

MyString(MyString&& str) {        std::cout << "Move Constructor is called! source: " << str._data << std::endl;        _len = str._len;        _data = str._data;        str._len = 0;        str._data = NULL;    }    MyString& operator=(MyString&& str) {        std::cout << "Move Assignment is called! source: " << str._data << std::endl;        if (this != &str) {            _len = str._len;            _data = str._data;            str._len = 0;            str._data = NULL;        }        return *this;    }

增加了转移构造函数和转移复制操作符后,我们的程序运行结果为 :

 Move Assignment is called! source: Hello  Move Constructor is called! source: World

左值右值判断

#include <iostream>#include <string>#include<vector>using namespace std;template<typename T>void PrintT(T& t){    cout << "lvaue" << endl;}template<typename T>void PrintT(T && t){    cout << "rvalue" << endl;}template<typename T>void TestForward(T && v){    PrintT(v);    PrintT(std::forward<T>(v));    PrintT(std::move(v));}int main (){    TestForward(1);    int x = 1;    TestForward(x);    TestForward(std::forward<int>(x));}

技术分享

std::forward会按参数原来的类型转发

std::move 转为右值

万能包装器

#include <iostream>#include <string>#include<vector>using namespace std;template<class Function, class... Args>inline auto FuncWrapper(Function && f, Args && ... args) ->     decltype(f(std::forward<Args>(args)...)) {    return f(std::forward<Args>(args)...);}void test0() { cout << "void" << endl; }int test1() { return 1; } int test2(int x) { return x; }string test3(string s1, string s2) { return s1 + s2; }void test() {    FuncWrapper(test0); //没有返回值,打印1    cout<<FuncWrapper(test1)<<endl; //返回1    cout<<FuncWrapper(test2, 1)<<endl; //返回1     cout<<FuncWrapper(test3, "aa", "bb")<<endl; //返回"aabb"}int main(){    test();}

 

成员的emplace_back

c++11中大部分容器都加了一个emplace_back成员函数,vector中它的定义是这样的:

template< class... Args >void emplace_back( Args&&... args );

这里的Args&&是一个未定的引用类型,因此它可以接收左值引用和右值引用,它的内部也是调用了std::forward实现完美转发的。因此如果我们需要往容器中添加右值、临时变量时,用emplace_back可以提高性能。

 

c++11 右值引用