C++11左值右值

对于C++11提出了左值、右值的概念。

左值 (location value)

  • 定义:左值是指可以出现在赋值运算符左侧的表达式。它通常代表一个持久的对象(即有持久的内存地址),可以在之后的代码中引用。

  • 特点

    • 有持久的内存地址。
    • 可以被修改。
    • 可以取地址(使用 & 运算符)。
  • 示例

  • int x = 10;  // x 是一个左值
    x = 20;      // 可以将新值赋给 x
    int* p = &x; // 可以取 x 的地址
    

右值 (read value)

  • 定义:右值是指临时对象或不具备持久存储的对象,通常用来表示计算结果。右值通常出现在赋值运算符右侧。

  • 特点

    • 没有持久的内存地址。
    • 通常是匿名的。
    • 不能取地址,或者取地址的意义不大。
  • 示例

  • int y = 5 + 10; // "5 + 10" 是一个右值
    int* p = &y;    // y 是一个左值,而 "5 + 10" 不是
    

右值引用

C++11 引入了右值引用(rvalue reference),这使得程序能够识别右值并进行优化,比如通过移动语义(move semantics)来提高性能。这可以通过使用 && 来定义右值引用。

  • 示例
  • void process(int&& val) {  // val 是一个右值引用
        // ...
    }
    
    process(42); // 42 是一个右值
    

总结

  • 左值:有持久性,可以取地址,能出现在赋值运算符的左侧。
  • 右值:没有持久性,通常是临时对象,出现在赋值运算符的右侧。

使用场景

了解左值和右值的概念有助于:

  • 理解 C++ 的资源管理与优化。
  • 编写高效的代码,特别是在处理移动语义和完美转发时。

案例实现

#include <iostream>
#include <string.h>
#include <algorithm>
#include <type_traits>


using namespace std;

class CharBuffer {
public:
	CharBuffer() :m_buff(nullptr), m_Size(0) {
		cout << "默认构造函数" << endl;
	}

	CharBuffer(unsigned int nSize) :m_buff(new char[nSize]), m_Size(nSize) {
		cout << "普通构造函数" << endl;
	}

	CharBuffer(CharBuffer& other) :m_buff(new char[other.m_Size]), m_Size(other.m_Size) {
		memcpy(m_buff, other.m_buff, m_Size);
		cout << "拷贝构造函数" << endl;
	}

	CharBuffer(CharBuffer&& other) :m_buff(other.m_buff), m_Size(other.m_Size) {
		other.m_buff = nullptr;
		other.m_Size = 0;
		cout << "移动构造函数" << endl;
	}

	CharBuffer& operator=(const CharBuffer& other) {
		if (m_Size == 0 || m_Size != other.m_Size) {
			if (m_Size != other.m_Size) {
				delete[] m_buff;
			}

			m_buff = new char[other.m_Size];
			m_Size = other.m_Size;
		}

		memcpy(m_buff, other.m_buff, m_Size);

		cout << "拷贝赋值运算符" << endl;
		return *this;
	}

	CharBuffer& operator=(CharBuffer&& other) {
		if (m_Size) {
			delete[] m_buff;
		}

		m_buff = other.m_buff;
		m_Size = other.m_Size;

		other.m_buff = nullptr;
		other.m_Size = 0;
		cout << "移动赋值运算符" << endl;
		return *this;
	}

	static CharBuffer& assign(CharBuffer& to, CharBuffer& from) {
		to = from;
		return to;
	}

	static CharBuffer& assign(CharBuffer& to, CharBuffer&& from) {
		to = from;
		return to;
	}

	~CharBuffer() {
		delete[] m_buff;
		cout << "析构函数" << endl;
	}

private:
	char* m_buff;
	unsigned int m_Size;
};

template <class T>
CharBuffer makeObj(T&& buf) {
	cout << "是否左值 :" << is_lvalue_reference<T&&>::value << endl;
	cout << "是否右值 :" << is_rvalue_reference<T&&>::value << endl;
	// 左值引用:为对象起一个别名
	// 右值引用:为即将废弃的对象续命
	return CharBuffer((T&&)buf);
}

CharBuffer getObj(int n) {
	CharBuffer buf(n);
	return buf;
}

int main()
{
	CharBuffer buf1(CharBuffer(100));
	cout << "-----------------------------------" << endl;
	// 移动构造
	CharBuffer buf2 = getObj(100);
	// 移动赋值
	buf2 = getObj(200);
	cout << "-----------------------------------" << endl;
	CharBuffer buf3;
	CharBuffer buf4(100);
	CharBuffer::assign(buf3, std::move(buf4));
	cout << "-----------------------------------" << endl;
	CharBuffer buf5(100);
	// 拷贝构造
	makeObj(buf5);
	cout << "-----------------------------------" << endl;
	// 移动构造
	makeObj(std::move(buf5));

	return 0;
}

执行结果如下:

### C++左值的概念及区别 #### 定义与基本概念 在 C++ 中,每个表达式都可以被分类为 **左值** 或者 ****。左值指的是那些可以在程序中通过名字访问的对象,而则是指那些没有持久化名字的临时对象。 - 左值是有名字的对象,可以通过 `&` 运算符获取其地址[^1]。 - 是没有名字的临时对象,无法对其应用取址运算符 `&`[^4]。 #### 细分C++11 和更高版本中,进一步细分为两种类型: - **纯(Prvalue)**: 表达式的计算结果是一个临时对象或字面量,例如 `3 + 4` 的结果就是一个纯[^4]。 - **将亡(Xvalue)**: 是一种特殊的,表示即将被销毁的对象,常见于 `std::move` 返回的结果以及某些函数调用返回的引用[^5]。 #### 主要区别 以下是左值的主要区别总结: | 特性 | 左值 | | |-------------------|----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| | 是否有名字 | 有固定的名字 | 没有持久化的名字 | | 能否取地址 | 可以通过 `&` 获取地址 | 不可以直接取地址 | | 生命周期 | 长生命周期 | 短生命周期 | | 示例 | 变量名、数组元素 | 函数返回、字面量、匿名临时对象 | #### 使用场景 ##### 左值的应用 - 左值可以绑定到左值引用 (`T&`) 上,允许修改原始对象的内容[^5]。 - 下列代码展示了如何使用左值引用: ```cpp int a = 10; int &ref_a = a; // ref_a 是左值引用 ref_a = 20; // 修改了 a 的 cout << a << endl; // 输出 20 ``` ##### 的应用 - 可以绑定到引用 (`T&&`) 上,用于实现高效的资源转移,避免不必要的拷贝操作。 - 移动语义的核心在于利用引用捕获临时对象并将其资源转移到目标对象中,从而提高性能[^2]。 - 下列代码演示了引用的作用: ```cpp #include <iostream> using namespace std; class MyClass { public: string data; MyClass(string d) : data(d) {} ~MyClass() { cout << "Destructor called on " << data << "\n"; } }; void moveResource(MyClass &&obj) { cout << "Moving resource from temporary object\n"; } int main() { MyClass temp("Temporary"); moveResource(std::move(temp)); // 将左值转化为引用传递 } ``` #### 总结 理解和掌握左值的区别及其应用场景对于编写高效且现代化的 C++ 程序至关重要。特别是随着 C++11 引入移动语义后,合理运用引用能够显著提升程序性能。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值