【C++】—— C++11新特性之 “右值引用和移动语义”

这篇具有很好参考价值的文章主要介绍了【C++】—— C++11新特性之 “右值引用和移动语义”。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

  • 本期,我们将要的介绍有关 C++右值引用 的相关知识。对于本期知识内容,大家是必须要能够掌握的,在面试中是属于重点考察对象。

目录

(一)左值引用和右值引用

1、什么是左值?什么是左值引用?

2、什么是右值?什么是右值引用?

(二)左值引用与右值引用比较

(三)右值引用使用场景和意义

(四)完美转发 

1、概念

2、模板中的&& 万能引用

3、std::forward

总结


(一)左值引用和右值引用

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。

1、什么是左值?什么是左值引用?

C++98/03 标准中就有引用,使用 "&" 表示。但此种引用方式有一个缺陷,即正常情况下只能操作 C++中的左值,无法对右值添加引用。举个例子:
 

int main()
{
	int num = 10;
	int& b = num; //正确
	int& c = 10; //错误

	return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【解释说明】

  • 如上所示,编译器允许我们为 num 左值建立一个引用,但不可以为 10 这个右值建立引用。因此,C++98/03 标准中的引用又称为左值引用。
     

那么到底什么是左值?什么是左值引用呢?

  1. 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边;
  2. 定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。
     

注意:虽然 C++98/03 标准不支持为右值建立非常量左值引用,但允许使用常量左值引用操作右值。也就是说,常量左值引用既可以操作左值,也可以操作右值,例如:
 

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;
}

2、什么是右值?什么是右值引用?  

我们知道,右值往往是没有名称的,因此要使用它只能借助引用的方式。这就产生一个问题,实际开发中我们可能需要对右值进行修改(实现移动语义时就需要),显然左值引用的方式是行不通的。


为此,C++11 标准新引入了另一种引用方式,称为右值引用,用 "&&" 表示:

  • 右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等;
  • 右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址
  • 右值引用就是对右值的引用,给右值取别名。

int main()
{
	double x = 1.1, y = 2.2;

	// 以下几个都是常见的右值
	10;
	x + y;
	fmin(x, y);

	// 以下几个都是对右值的右值引用
	int&& rr1 = 10;
	double&& rr2 = x + y;
	double&& rr3 = fmin(x, y);

	return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 但是如果是下面这几个表达式,就会发生报错现象:

10 = 1;
x + y = 1;
fmin(x, y) = 1;

输出显示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址。例如下面代码所示:

int main()
{
	double x = 1.1, y = 2.2;

	int&& rr1 = 10;
	double&& rr2 = x + y;
	cout << rr1 << " " << rr2 << " " << endl;

	rr1 = 20;
	rr2 = 5.5;
	cout << rr1 << " " << rr2 << " " << endl;

	return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 当我们不想被修改时,我们可以加上 【const】关键字:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

【解释说明】

  1. 不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1;
  2. 如果不想rr1被修改,可以用const int&& rr1 去引用;
  3. 是不是感觉很神奇这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要
     

(二)左值引用与右值引用比较

左值引用总结:

  • 1. 左值引用只能引用左值,不能引用右值。
  • 2. 但是const左值引用既可引用左值,也可引用右值
int main()
{
	// 左值引用只能引用左值,不能引用右值。
	int a = 10;
	int& ra1 = a; // ra为a的别名
    
    return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 又例如以下示例:

int main()
{
	// 左值引用只能引用左值,不能引用右值。
	int a = 10;
	int& ra2 = 10; // 编译失败,因为10是右值

    return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 左值引用只能引用左值,不能引用右值。但是当我们加上 const 时,此时左值引用可以给右值取别名:

int main()
{
    int a = 10;
    // const左值引用既可引用左值,也可引用右值。
	const int& ra3 = 10;
	const int& ra4 = a;
    
    return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

【解释说明】

值得一提的是,虽然C++ 语法上是支持定义常量右值引用的,但这种定义出来的右值引用并无实际用处:

const int& ra3 = 10;
  1. 一方面,右值引用主要用于移动语义和完美转发,其中前者需要有修改右值的权限;
  2. 其次,常量右值引用的作用就是引用一个不可修改的右值,这项工作完全可以交给常量左值引用完成。
     

右值引用总结:

  • 1. 右值引用只能右值,不能引用左值。
  • 2. 但是右值引用可以move以后的左值。
     

代码展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 引用左值会发生报错行为:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言


通过 move 可以支持将左值转换为右值引用 

 在C++中,move是一个函数模板,可以将给定的对象转换为对应的右值引用。它并不执行实际的内存移动操作,而是将对象标记为可以进行移动操作的右值。这样,用户可以利用该标记来实现更高效的移动语义。

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言


(三)右值引用使用场景和意义

前面我们可以看到左值引用既可以引用左值和又可以引用右值,那为什么C++11还要提出右值引用呢?是不是化蛇添足呢?下面我们来看看左值引用的短板,右值引用是如何补齐这个短板的!

现有以下代码: 

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【解释说明】

首先,对于上述代码中的 res1 和 res2 ,它们分别为左值和右值;

紧接着大家想想,我们对左值和对右值拷贝有没有什么区别呢?

  • 如果是内置类型,他们其实区别不是很大,但是对于自定类型他们的区别可就很大了,
  • 因为自定义类型的右值,一般很多地方又把它叫做将亡值。通常都是一些表达式的返回值、一个函数调用等;
  • 而对于右值又分为 纯右值(一般来说是内置类型)和将亡值(一般来说是自定义类型)

对于上述的 res1,它作为一个左值,我们不能对其进行操作,只能去做深拷贝。因为虽然看起来这里是一个赋值,其实应该是拷贝构造;

而对于 res2 来说,它本身是右值,假如是自定义类型作为一个将亡值,我们就没有必要去对其进行拷贝操作。此时就引出了关于右值引用实现引动构造的概念。


例如现在有这样一个我们手写模拟的 string :

namespace zp
{
	class string
	{
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			//cout << "string(char* str)" << endl;

			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		// s1.swap(s2)
		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		// 拷贝构造
		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()
		{
			delete[] _str;
			_str = nullptr;
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;

				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
			}

			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		//string operator+=(char ch)
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		string operator+(char ch)
		{
			string tmp(*this);
			tmp += ch;
			return tmp;
		}

		const char* c_str() const
		{
			return _str;
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity; // 不包含最后做标识的\0
	};
}

当我们再这样的场景在来观察上述的 res1 和res2:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 我们可以发现此处的右值发生的是相应的深拷贝,这样显然是会造成不必要的浪费的。为了解决上述这样的问题,我们就可以引入 “移动构造” 这样的概念:

// 移动构造
string(string&& s)
	:_str(nullptr)
{
	cout << "string(string&& s) -- 移动拷贝" << endl;
	swap(s);
}

紧接着,再次运行上述代码,我们可以发现编译器会去自动识别:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

此时,当我们就是想把 s1 转为右值可以怎么做呢?其实很简单(这里就体现了move):

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

我们通过调试也可以发现此时确实达到了预期的效果:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【小结】

通过上述我们可以发现左值引用的好处就是直接减少拷贝

左值引用的使用场景可以分为以下两个部分:

  • 做参数和做返回值都可以提高效率

左值引用的短板:

  • 但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。

例如现在有以下这样的代码: 

    zp::string to_string(int value)
	{
		bool flag = true;
		if (value < 0)
		{
			flag = false;
			value = 0 - value;
		}

		zp::string str;
		while (value > 0)
		{
			int x = value % 10;
			value /= 10;

			str += ('0' + x);
		}

		if (flag == false)
		{
			str += '-';
		}

		std::reverse(str.begin(), str.end());
		return str;
	}

【说明】

  • zp::string to_string(int value)函数中可以看到,这里只能使用传值返回,传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 紧接着,我们去打印看结果是什么:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 此时,传值返回带来的代价得到了极大的解决:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 右值引用和移动语义解决上述问题:

  • 在zp::string中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己;

再运行上面zp::to_string的两个调用,我们会发现,这里没有调用深拷贝的拷贝构造,而是调用了移动构造,移动构造中没有新开空间,拷贝数据,所以效率提高了。

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言


c++11 不仅仅有移动构造,还有移动赋值:

在zp::string类中增加移动赋值函数,再去调用zp::to_string(1234),不过这次是zp::to_string(1234)返回的右值对象赋值给ret1对象,这时调用的是移动构造。

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【解释说明】

  • 这里运行后,我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收,编译器就没办法优化了。zp::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值,调用了移动构造。然后在把这个临时对象做为 zp::to_string 函数调用的返回值赋值给ret1,这里调用的移动赋值。

(四)完美转发 

1、概念

  • 完美转发(perfect forwarding)是C++11引入的一项特性,旨在实现在函数模板中对参数类型进行精确传递的能力;
  • 它主要用于保留传递到函数模板的实参的值类别,并将其转发到内部调用的函数,从而实现类型和值类别的完全保持;

举个例子:

template<typename T>
void PerfectForward(T t)
{
    Fun(t);
}

【解释说明】

  1. 如上所示,PerfectForward() 函数模板中调用了 Func() 函数;
  2. 在此基础上,完美转发指的是:如果 PerfectForward() 函数接收到的参数 t 为左值,那么该函数传递给 Func() 的参数 t 也是左值;
  3. 反之如果 function() 函数接收到的参数 t 为右值,那么传递给 Func() 函数的参数 t 也必须为右值。

使用任何一种引用形式,可以实现转发,但无法保证完美。因此如果使用 C++ 98/03 标准下的 C++ 语言,我们可以采用函数模板重载的方式实现完美转发,例如:

template<typename T>
void Func(T& arg)
{
    cout << "左值引用:" << arg << endl;
}

template<typename T>
void Func(T&& arg)
{
    cout << "右值引用:" << arg << endl;
}

template<typename T>
void PerfectForward(T&& arg)
{
    Func(arg);  // 利用重载的process函数进行处理
}

int main()
{
    int value = 42;
    PerfectForward(value);       // 传递左值
    PerfectForward(123);         // 传递右值

    return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【解释说明】

  1. 在上述示例中,我们定义了两个重载的函数模板 Func,一个接收左值引用参数T& arg,另一个接收转发引用参数T&& arg;
  2. 然后,我们再定义一个模板函数PerfectForward,其参数也是转发引用T&& arg。在PerfectForward函数内部,我们通过调用Func函数来处理传递的参数;
  3. 通过函数重载的机制,传递的左值参数将匹配到接收左值引用的Func函数,传递的右值参数则匹配到接收转发引用的Func函数,从而正确地进行区分和处理;
  4. 通过函数模板的重载,我们可以根据参数类型将左值和右值区分开来,并分别处理,实现了针对不同值类别的精确匹配和操作。

2、模板中的&& 万能引用

显然,上述使用重载的模板函数实现完美转发也是有弊端的,此实现方式仅适用于模板函数仅有少量参数的情况,否则就需要编写大量的重载函数模板,造成代码的冗余。为了方便用户更快速地实现完美转发,C++ 11 标准中允许在函数模板中使用右值引用来实现完美转发。

还是以 PerfectForward() 函数为例,在 C++11 标准中实现完美转发,只需要编写如下一个模板函数即可:

//模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
template<typename T>
void PerfectForward(T&& t)
{
    Fun(t);
}

以如下代码为例:

void Fun(int& x) 
{ 
	cout << "左值引用" << endl;
}
void Fun(const int& x)
{
	cout << "const 左值引用" << endl; 
}
void Fun(int&& x)
{
	cout << "右值引用" << endl; 
}
void Fun(const int&& x) 
{
	cout << "const 右值引用" << endl; 
}

template<typename T>
void PerfectForward(T&& t)
{
	Fun(t);
}
int main()
{
	PerfectForward(10); // 右值

	int a;
	PerfectForward(a); // 左值
	PerfectForward(std::move(a)); // 右值

	const int b = 8;
	PerfectForward(b); // const 左值
	PerfectForward(std::move(b)); // const 右值
	return 0;
}

输出展示:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

 【解释说明】

  1. 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
  2. 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
  3. 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
  4. 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
     

3、std::forward

C++11 标准的开发者已经帮我们想好的解决方案,该新标准还引入了一个模板函数 forword<T>(),我们只需要调用该函数,就可以很方便地解决此问题。

  1. 完美转发通常与转发引用(forwarding reference)和 std::forward 函数一起使用;
  2. 转发引用是一种特殊的引用类型,使用&&语法进行声明,用于在函数模板中捕获传递的实参;
  3. std::forward 是一个模板函数,用于在函数模板内部将转发引用作为右值或左值引用进行转发。

如下演示了该函数模板的用法:

void Fun(int& x) 
{ 
	cout << "左值引用" << endl;
}
void Fun(const int& x)
{
	cout << "const 左值引用" << endl; 
}
void Fun(int&& x)
{
	cout << "右值引用" << endl; 
}
void Fun(const int&& x) 
{
	cout << "const 右值引用" << endl; 
}

template<typename T>
void PerfectForward(T&& t)
{
	// forward<T>(t)在传参的过程中保持了t的原生类型属性。
	Fun(std::forward<T>(t));
}
int main()
{
	PerfectForward(10); // 右值

	int a;
	PerfectForward(a); // 左值
	PerfectForward(move(a)); // 右值

	const int b = 8;
	PerfectForward(b); // const 左值
	PerfectForward(move(b)); // const 右值
	return 0;
}

程序执行结果为:

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

通过完美转发,我们可以在函数模板中正确处理传递实参的值类别,并将其转发到内部函数,以达到类型和值类别的完全保持,提高代码的灵活性和效率。


总结

学到这里,一些读者可能无法记清楚左值引用和右值引用各自可以引用左值还是右值,这里给大家一张表格,方便大家记忆:
 

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言

  •  表中,Y 表示支持,N 表示不支持。

以上便是关于左值引用和右值引用的全部知识讲解!感谢大家的观看与支持!!!

【C++】—— C++11新特性之 “右值引用和移动语义”,C++学习,c++,开发语言文章来源地址https://www.toymoban.com/news/detail-670938.html

到了这里,关于【C++】—— C++11新特性之 “右值引用和移动语义”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c++积累8-右值引用、移动语义

    1.1 背景 c++98中的引用很常见,就是给变量取个别名,具体可以参考c++积累7 在c++11中,增加了右值引用的概念,所以c++98中的引用都称为左值引用 1.2 定义 右值引用就是给右值取个名字,右值有了名字之后就成了普通变量,可以像使用左值一样使用。 语法:数据类型 变量名

    2023年04月23日
    浏览(38)
  • 【重学C++】04 | 说透C++右值引用、移动语义、完美转发(上)

    【重学C++】04 | 说透C++右值引用、移动语义、完美转发(上) 大家好,我是只讲技术干货的会玩code,今天是【重学C++】的第四讲,在前面《03 | 手撸C++智能指针实战教程》中,我们或多或少接触了右值引用和移动的一些用法。 右值引用是 C++11 标准中一个很重要的特性。第一

    2024年02月06日
    浏览(45)
  • 【重学C++】05 | 说透右值引用、移动语义、完美转发(下)

    【重学C++】05 | 说透右值引用、移动语义、完美转发(下) 大家好,我是只讲技术干货的会玩code,今天是【重学C++】的第五讲,在第四讲《【重学C++】04 | 说透右值引用、移动语义、完美转发(上)》中,我们解释了右值和右值引用的相关概念,并介绍了C++的移动语义以及如

    2024年02月06日
    浏览(40)
  • C++右值引用(左值表达式、右值表达式)(移动语义、完美转发(右值引用+std::forward))(有问题悬而未决)

    在 C++ 中,表达式可以分为左值表达式和右值表达式。左值表达式指的是可以出现在赋值语句左边的表达式,例如变量、数组元素、结构体成员等;右值表达式指的是不能出现在赋值语句左边的表达式,例如常量、临时对象、函数返回值等。 右值是指将要被销毁的临时对象或

    2024年02月04日
    浏览(45)
  • [开发语言][c++]:左值、右值、左值引用、右值引用和std::move()

    写在前面: 如果你也被 左值、右值、左值引用、右值引用和std::move 搞得焦头烂额,相关概念和理解不够深入,或者认识模棱两可,那么这篇文章将非常的适合你,耐心阅读,相信一定会有所收获~~ 左值: 可以取地址、位于等号左边 – 表达式结束后依然存在的持久对象

    2024年02月02日
    浏览(62)
  • 从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值

    目录 1. 列表初始化initializer_list 2. 前面提到的一些知识点 2.1 小语法 2.2 STL中的一些变化 3. 右值和右值引用 3.1 右值和右值引用概念 3.2 右值引用类型的左值属性 3.3 左值引用与右值引用比较 3.4 右值引用的使用场景 3.4.1 左值引用的功能和短板 3.4.2 移动构造 3.4.3 移动赋值

    2024年02月12日
    浏览(36)
  • 【C++11】 initializer_list | 右值引用 | 移动构造 | 完美转发

    { } 初始化 C++11 扩大了括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义类型, 使用初始化列表,可添加等号(=),也可不添加 将1赋值给x1,x2处省略了赋值符号,将5赋值给x2 同样也可以将new开辟4个int的空间初始化为0 创建对象时,可以使用列

    2024年02月08日
    浏览(70)
  • 【C++】C++11右值引用

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.什么是左值什么是右值 左值 右值 2.什么是左值引用什么是右值引用 左

    2024年04月22日
    浏览(49)
  • C++ Primer阅读笔记--对象移动(右值引用、移动迭代器和引用限定符的使用)

    目录 1--右值引用 2--std::move 3--移动构造函数 4--移动赋值运算符 5--移动迭代器 6--引用限定符         右值引用必须绑定到右值的引用,通过 获得右值引用;         右值引用只能绑定到 临时对象 (即将被销毁的对象),即所引用的对象将要被销毁,对象没有其他用户;

    2024年02月10日
    浏览(37)
  • 【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式

    在C++11之前,我们只有引用的概念,没有接触到所谓的左值引用或者是右值引用这种概念,从C++11开始,增加了右值引用的概念,那么现在我们将对引用进行一个概念上的区分。在此之前我们所说的引用都是左值引用,对于左值引用相关的内容,可以去看一看博主之前写的文章

    2024年02月15日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包