C++11之一场名为“搬家”的 C++ 之旅

一、左值VS右值

在C++中,每一个变量或者表达式,都有一个身份:要么是左值,要么是右值

  • 左值:有名字、有固定住址的永久居民

比如:int a = 10;这里的a就是左值。你看可以通过&a找到它的家庭住址

  • 右值:没名字、四处漂泊的临时过客

比如10,a + 5,或者一个函数返回的临时对象。它们马上就要消息了,你没法用&取它们的地址

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int a = 10; // a 是左值,10 是右值
    
    cout << "a 的地址: " << &a << endl; // ✅ 合法,a 有地址
    // cout << &10 << endl;            // ❌ 非法,10 没有地址(右值)
    // cout << &(a+5) << endl;         // ❌ 非法,a+5 的结果没有地址(右值)
    
    return 0;
}

二、引用是什么?

引用就是给变量取个"外号",操作外号就等于操作变量本身

1、左值引用(&):只能给持久居民起外号

bash 复制代码
int a = 10;
int& ref1 = a;      // ✅ 合法,ref1 是 a 的外号
// int& ref2 = 10;  // ❌ 非法,不能给临时过客起外号(没住址)

2、常引用(const &):老好人谁都能绑

cpp 复制代码
int a = 10;
const int& ref3 = a;  // ✅ 合法
const int& ref4 = 10; // ✅ 合法!虽然是临时过客,但老好人给它续命了(延长了生命周期)
// ref4 = 20;         // ❌ 非法,因为是 const(只读外号)

3、右值引用(&&):专为临时过客准备的外号

cpp 复制代码
int a = 10;
// int&& ref5 = a;    // ❌ 非法,右值引用不能绑持久居民(左值)
int&& ref6 = 10;      // ✅ 合法,绑定临时过客(右值)
int&& ref7 = a + 5;   // ✅ 合法,绑定临时过客(右值)

注意:右值引用变量自己,是个左值!

这一点极其重要!C++ 规定:只要一个变量有名字,它就是左值 。所以 ref6 虽然类型是右值引用,但它自己有名字,它就是个左值

cpp 复制代码
int&& ref8 = 10;
// int&& ref9 = ref8;  // ❌ 非法!因为 ref8 有名字,被当作左值!
int&& ref9 = std::move(ref8); // ✅ 必须用 std::move 把它重新变成右值

三、为什么要有右值引用?

假设你要写一个 String 类,里面有一个指针 char* ptr;。

  • 当你把一个左值赋给另一个左值 时,你不能偷别人的数据(别人还要用),所以你只能深拷贝 (重新申请一块内存,把字串复制过去)。这叫拷贝赋值。

  • 但是,当你把一个右值(临时对象)赋给另一个左值 时,反正临时对象马上要死了,我们为什么不直接把它的指针"偷"过来 呢?这就叫移动赋值!

四、std::move是什么?

真相:std::move 根本没有移动任何东西!

它就像一个"魔法标签"。你把一个左值传进去,它就给你贴个标签:"虽然它是个左值,但我宣布,从现在起,你就把它当成右值用!"

它的底层实现其实是强制类型转换:

cpp 复制代码
// 你写:
std::move(a);
// 编译器实际干的事:
static_cast<int&&>(a); // 强行把 a 转成右值引用类型

被 std::move 标记过的左值,它的资源就可以被安全地"偷走"了。所以 std::move 最好只用在"你确定以后不再使用这个变量"的时候

相关推荐
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
2601_962071572 小时前
类变量和全局变量的查找路径有什么区别?
开发语言·python
hetao17338373 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
\光辉岁月/3 小时前
5.java-数组
java·开发语言
Java后端的Ai之路3 小时前
Python进阶探索29_eval内置函数
开发语言·python·探索·eval·内置函数
谢亮_vipxieliang3 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
longlongzihan3 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
时间的拾荒人3 小时前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
郑州光合科技余经理4 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程