45右值引用

右值引用

参考

  • 左值有内存有名字,是可寻址的变量,有持久性。
  • 右值没内存没名字,一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。C++中的临时量均作为右值。拷贝构造函数或运算符重载可以使用右值引用作为函数参数,以处理临时量。

左值引用和右值引用

  • 一般左值引用只能绑定左值,右值引用只能绑定右值。
  • 特殊情况 const char& = 'a'其中'a'是右值,但可以绑定至常左值引用上
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "cstring"
using namespace std;

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

    //左值引用参数的拷贝构造
    CMyString(const CMyString& str)
    {
        mptr = new char[strlen(str.mptr) + 1];
        strcpy(mptr, str.mptr);
        cout << "CMyString(const CMyString&)" << endl;
    }
    //右值引用参数的拷贝构造,临时对象会调用
    CMyString(CMyString&& str)
    {
        mptr = str.mptr;
        str.mptr = nullptr;
        cout << "CMyString(CMyString&&)" << endl;
    }

    //右值引用参数的运算符重载
    CMyString& operator=(CMyString&& str)
    {
        cout << "String& operator=(String&&)" << endl;
        if (this == &str)
            return *this;

        delete[] mptr;

        mptr = str.mptr;
        str.mptr = nullptr;

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

private:
    char* mptr;
    friend CMyString operator+(const CMyString& lhs,
                               const CMyString& rhs);
    friend ostream& operator<<(ostream& out, const CMyString& str);
};

CMyString GetString(CMyString& str)
{
    const char* pstr = str.c_str();
    CMyString tmpStr(pstr);
    cout << "--------------------" << endl;
    return tmpStr;  //本来这里会调用左值引用构造临时对象,但由于tmpStr是临时变量,现在会匹配到右值引用拷贝构造
}

//CMyString operator+(const CMyString& lhs,
//                    const CMyString& rhs)
//{
//    cout << "--------------------" << endl;
//    char* ptmp = new char[strlen(lhs.mptr) + strlen(rhs.mptr) + 1];  //存在内存泄露
//    strcpy(ptmp, lhs.mptr);
//    strcat(ptmp, rhs.mptr);
//    return CMyString(ptmp);
//}

CMyString operator+(const CMyString& lhs,
                    const CMyString& rhs)
{
    cout << "--------------------" << endl;
    // char* ptmp = new char[strlen(lhs.mptr) + strlen(rhs.mptr) + 1];
    CMyString tmpStr;
    tmpStr.mptr = new char[strlen(lhs.mptr) + strlen(rhs.mptr) + 1];
    strcpy(tmpStr.mptr, lhs.mptr);
    strcat(tmpStr.mptr, rhs.mptr);
    return tmpStr;  //tmpStr是右值 调用右值引用的拷贝构造给main中的临时量
}

ostream& operator<<(ostream& out, const CMyString& str)
{
    out << str.mptr;
    return out;
}

int main()
{
    CMyString str1 = "aaaaaaaaaaaaaaaaa";
    CMyString str2 = "bbbbbbbbbbbbbb";
    CMyString str3 = GetString(str1); //main中返回的临时量也属于右值,重载右值引用的等号运算符
    CMyString str4 = str1 + str2; //重载右值引用的拷贝构造  
    cout << str3 << endl;
    cout << "--------------------" << endl;
    return 0;
}
posted @ 2024-03-04 21:46  SIo_2  阅读(26)  评论(0)    收藏  举报