c++

C++11:右值引用和转移赋值

2020-06-20  本文已影响0人  行走的代码

1.首先认识左值和右值的定义:

左值:表达式可以引用到一个对象,并且这个对象是一块内存空间并可以检测和存储,这个表示即是左值。

右值:直接引用了一个存储在内存地址中的数据。

右值最大限度只能被一个常量引用:

1
const int &a = 1;
规则:临时变量是右值,且可以改变:

1
T().set().get()
T为临时变量,set()设置新值,get()获取更改后的值。

2.首先写一个MyString类:

#include<vector>
class MyString
{
private:
    int _len;
    char* _data;
    void init_data(const char* str)
    {
        _data = new char[_len+1];
        memcpy(_data,str,_len);
        _data[_len] = '\0';
    }
public:
    MyString()
    {
        _len = 0;
        _data = NULL;
    }
    MyString(const char* str)
    {
        _len = strlen(str);
        init_data(str);
    }
    MyString(const MyString& rhs)
    {
        _len = rhs._len;
        init_data(rhs._data);
    }
    MyString& operator=(MyString& rhs)
    {
        if(this != &rhs)
        {
            _len = rhs._len;
            init_data(rhs._data);
            //MyString(rhs);
        }
        return *this;
    }
    virtual ~MyString()
    {
        if(_data) free(_data);
    }
};
int main()
{
    Mystring a;
    a = MyString("Hello");
    std::vector<MyString> vec;
    vec.push_back(MyString("World"));
}

左值和右值引用符号区别:

void print_value(int& a)
{
  std::cout << "LValue" << endl;
}
void print_value(int&& a)
{
  std::cout << "RValue" << endl;
}

右值引用实际是用来支持转移赋值和转移构造:

MyString(MyString&& rhs)        //不包含const
{
    _len = rhs._len;
    _data = rhs._data;
    rhs._len = 0;
    rhs._data = NULL;
}
MyString& operator(MyString&& rhs)  //不包含 const
{
    if(this != &rhs)
    {
        _len = rhs._len;
        _data = rhs._data;
        rhs._len = 0;
        rhs._data = NULL;
    }
    return *this;
}

转移构造和赋值的好处是:节省了资源,提高了程序效率。

std::move是标准库提供的将一个命名对象转换为一个临时对象(右值)来支持转移构造和赋值:

template <class T> void swap(T& a, T& b)
{
    T c(std::move(a));
    a=std::move(b);
    b=std::move(c);
}
template <class T, size_t N> void swap(T (&a)[N], T(&b)[N])
{
    for(size_t i = 0; i<N; ++i) swap(a[i], b[i]);
}

这样提高了swap效率。

未显式定义转移构造函数和转移赋值函数,会使用默认的。但有几种情况需要显式定义:

  1. 成员中含有裸指针,用默认的存在释放问题;
  2. 自定义了构造函数和赋值函数,那么需要显式定义move的方法;
  3. 显式定义析构函数,需要显式定义move方法;


    v2-c05999fd24c153670011c7eb161a7d8a_720w.jpg
上一篇下一篇

猜你喜欢

热点阅读