左值右值,右值拷贝右值赋值,move&&forward

一、左值右值

  • 左值:有名字、有内存

  • 右值:没名字(临时量)、没内存

  • 无法将左值绑定到右值引用

  • 无法将右值绑定到左值引用

  • 常引用既可以绑定右值,也可以绑定左值

  • 一个右值引用变量本身是一个左值

    # include <iostream>
    
    int main()
    {
        int a = 10;
        int &b = a; // 左值:有名字、有内存;右值:没名字(临时量),没内存
        // int &&c = a; // 无法将左值绑定到右值引用
    
        // int &c = 20; // 无法将右值绑定到左值引用
        /*
              常引用内部实现如下:
                  int temp = 20;
                  const int &c = temp;
          */
        const int &c = 20; // 常引用
    
        /*
              内部实现如下:
                  int temp = 20;
                  int &&d = temp;
          */
        int &&d = 20;
        int &f = d; // 一个右值引用变量本身是一个左值
    
        return 0;
    }
      
    

二、右值拷贝构造函数和右值赋值运算符

下面以手写的CMyString类进行介绍

# include <iostream>
# include <cstring>

class CMyString {
public:
    CMyString(const char* str = nullptr)
    {
        std::cout << "CMyString(const char*)" << std::endl;
        if (str)
        {
            mptr = new char[strlen(str) + 1];
            strcpy(mptr, str);
        }
        else
        {
            mptr = new char[1];
            *mptr = '\0';
        }
    }

    // 左值引用的拷贝构造函数
    CMyString(const CMyString& other)
    {
        std::cout << "CMyString(const CMyString&)" << std::endl;
        mptr = new char[strlen(other.mptr) + 1];
        strcpy(mptr, other.mptr);
    }

    // 右值引用的拷贝构造函数
    CMyString(CMyString&& other) noexcept
    {
        std::cout << "CMyString(CMyString&&)" << std::endl;
        mptr = other.mptr;
        other.mptr = nullptr;
    }

    // 左值赋值运算符
    CMyString& operator=(const CMyString& other)
    {
        std::cout << "CMyString& operator=(const CMyString&)" << std::endl;
        if (this == &other)
            return *this;

        delete[] mptr;
        mptr = new char[strlen(other.mptr) + 1];
        strcpy(mptr, other.mptr);
        return *this;
    }

    // 右值赋值运算符
    CMyString& operator=(CMyString&& other) noexcept
    {
        std::cout << "CMyString& operator=(CMyString&&)" << std::endl;
        if (this == &other)
            return *this;

        delete[] mptr;
        mptr = other.mptr;
        other.mptr = nullptr;
        return *this;
    }

    ~CMyString()
    {
        std::cout << "~CMyString()" << std::endl;
        delete[] mptr;
        mptr = nullptr;
    }

    const char* c_str() const
    {
        return mptr;
    }

private:
    char* mptr;
};

CMyString getString(CMyString& s)
{
    const char* p = s.c_str();
    CMyString temp(p);
    return temp;
}

int main()
{
    CMyString s1("aaaaaaaa");
    CMyString s2;
    s2 = getString(s1);
    std::cout << s2.c_str() << std::endl;
    return 0;
}

三、std::move && std::forward

  • 模板类型推导
  • 引用折叠
  • std::move()
  • std::forward()
# include <iostream>

// 1、模板函数的类型推演+引用折叠
// & + && -> &
// && + && -> &&
template<typename Ty>
void push_back(Ty &&val) // 右值引用变量本身是一个左值
{
    if (full()) 
        expand();

    // 2、std::move():得到左值的右值类型
    // 3、std::forward():类型的完美转发,能够识别左值还是右值
    _allocator.construct(_last, std::forward(val));
    _last++;
}

int main()
{
    CMyString s1("aaaa");
    push_back(s1); // CMyString&
    push_back(CMyString("bbbb")); // CMyString&&
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值