码迷,mamicode.com
首页 > 编程语言 > 详细

c++11 右值引用

时间:2016-09-11 00:08:53      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

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 右值引用

标签:

原文地址:http://www.cnblogs.com/yuguangyuan/p/5860626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!