0
点赞
收藏
分享

微信扫一扫

Azure Machine Learning - 视频AI技术

云竹文斋 2024-01-14 阅读 8

右值引用和移动语义

什么是左值?什么是左值引用?
int main()
{
    // 以下的p、b、c、*p都是左值
    int* p = new int(0);
    int b = 1;
    const int c = 2;
 
    // 以下几个是对上面左值的左值引用
    int*& rp = p;
    int& rb = b;
    const int& rc = c;
    int& pvalue = *p;
    return 0;
}
什么是右值?什么是右值引用?

在这里插入图片描述
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感觉很神奇;
这个了解一下,实际中右值引用的使用场景并不在于此,这个特性也不重要。

在这里插入图片描述

左值引用与右值引用比较
  • 左值引用总结:
  1. 左值引用只能引用左值,不能引用右值。
  2. 但是const左值引用既可引用左值,也可引用右值。
int main()
{
    // 左值引用只能引用左值,不能引用右值。
    int a = 10;
    int& ra1 = a; // ra为a的别名
    //int& ra2 = 10; // 编译失败,因为10是右值
 
    // const左值引用既可引用左值,也可引用右值。
    const int& ra3 = 10;
    const int& ra4 = a;
 
    return 0;
}
  • 右值引用总结:
  1. 右值引用只能右值,不能引用左值。
  2. 但是右值引用可以move以后的左值。
    在这里插入图片描述
左值引用的意义
void func1(string s)
{}
 
void func2(const string& s)
{}
 
const string& func3(const string& s)
{
    //....
    return s;
}
string func4(const string& s)
{
    //....
    string ret(s);
 
    return ret;
}
int main()
{
    string s1("hello world");
 
    func1(s1);//传值传参
    func2(s1);//传引用传参
 
    string s2 = func3(s1);//函数传返回值
//这里用左值引用返回却不行,因为ret是临时变量,出了函数会销毁,无法用左值引用返回
    func4(s1);
    
    return 0;
}

右值引用的使用场景

我们给string实现上移动构造和移动赋值

       // 拷贝构造
		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 拷贝构造-深拷贝" << endl;
			string tmp(s._str);
			swap(tmp);
		}
		// 拷贝赋值
		string& operator=(const string& s)
		{
			cout << "string& operator=(string s) -- 拷贝赋值-深拷贝" << endl;
			string tmp(s);
			swap(tmp);
			return *this;
		}
         // 移动构造
		string(string&& s)
			:_str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			cout << "string(string&& s) -- 移动构造" << endl;
			swap(s);
		}
		// 移动赋值
		string& operator=(string&& s)
		{
			cout << "string& operator=(string&& s) -- 移动赋值" << endl;
			swap(s);
			return *this;
		}

在这里插入图片描述


举报

相关推荐

0 条评论