右值 引用
- 左值:有内存有名字,是可寻址的变量,有持久性。
- 右值:没内存没名字,一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。C++中的临时量均作为右值。拷贝构造函数或运算符重载可以使用右值引用作为函数参数,以处理临时量。
CTest t1 = CTest(2);//右侧即为没有名字的右值,创建的临时对象
临时对象的生命周期:所在的语句内。出了语句,就不存在了!!
1、在C++中,std::move
函数的主要目的是:将一个左值对象转换为右值引用,从而触发移动语义,允许对象之间的资源转移,而不是进行深拷贝。
不能将右值转换为左值引用!!
2、左值引用和右值引用
- 一般左值引用只能绑定左值,右值引用只能绑定右值。
- 特殊情况
const char& = 'a'
其中'a'
是右值,但可以绑定至常左值引用上
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "cstring"
using namespace std;class CMyString
{
public:CMyString(const char* p = nullptr){cout << "CMyString(const char*)" << endl;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);//先返回再析构:因为new赋给tmpStr,出了函数作用域,临时变量就会调用自身析构函数~CMyString(),从而deletereturn 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中返回的临时量也属于右值,重载右值引用的等号运算符//1.调用operator+,2.调用右值引用的拷贝构造CMyString str4 = str1 + str2; //重载右值引用的拷贝构造 cout << str3 << endl;cout << "--------------------" << endl;return 0;
}
以上,