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++ 中,表达式的分类对于理解引用至关重要。左值 (lvalue) 表达式通常表示具有持久状态的对象,而 (rvalue) 则指临时对象或字面量。 - **左值引用 (`T&`)**:只能绑定到左值,允许修改所引用的对象。 - **引用 (`T&&`)**:专门设计来绑定到,支持移动语义和完美转发[^1]。 #### 使用场景对比 | 类型 | 非常量左值引用 `T&` | 常量左值引用 `const T&` | 非常量引用 `T&&` | | --- | --- | --- | --- | | 绑定至左值 | 支持 | 支持 | 不支持 | | 绑定至 | 不支持 | 支持 | 支持 | 非常量左值引用主要用于传递参数以便函数内部能改变调用者提供的变量;常量左值引用则广泛应用于避免大对象复制开销的同时保持只读访问权限。特别地,在现代 C++ 编程实践中,非常量引用主要服务于两个目的: - 实现高效的资源转移——即所谓的“移动语义”,通过直接接管现有资源而非深拷贝; - 协助模板元编程中的“完美转发”。 ```cpp // 移动语义示例 class Widget { public: // 拷贝构造函数 Widget(const Widget &other); // 移动构造函数 Widget(Widget &&other) noexcept; }; std::vector<Widget> v; v.push_back(Widget()); // 调用了移动构造函数而不是拷贝构造函数 ``` #### 特殊情况说明 得注意的是,虽然常规情况下引用不允许绑定到左值上,但在特定条件下可以通过标准库提供的 `std::move()` 函数显式转换为可被引用捕获的状态。这并不意味着原对象真正变成了,而是告诉编译器该对象即将废弃,从而启用潜在的性能优化措施[^2]。 ```cpp int a = 42; int&& rref = std::move(a); // 显式将左值转成引用可以接受的形式 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值