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 最好只用在"你确定以后不再使用这个变量"的时候

相关推荐
starzy19904 小时前
深入理解Scala隐式值:编译期自动装配
开发语言·后端·scala
布莱克6054 小时前
Swift 条件语句详解:从 if 到 switch 的完整指南
开发语言·ssh·swift·switch·条件语句·guard·if
汉克老师5 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
吴可可1235 小时前
ActiveX调用WScript.Shell原理揭秘
开发语言
晴天的雨.9926 小时前
【C++】继承篇
java·开发语言·c++
SomeOtherTime6 小时前
第 1 讲:内存布局与所有权解剖——栈帧、胖指针与“移动/拷贝”在汇编层面的真实面目
java·开发语言·汇编
青少儿编程课堂6 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
another heaven6 小时前
【C/C++ 第一次跨越(上):用 C++11/14 停止制造新的旧代码】
c语言·c++·制造
qq_406981036 小时前
c++ lamda(三)Lambda表达式
java·前端·c++
总要学点什么6 小时前
第106篇:三维特效-流动线效果——让一颗光点沿整条线一路滚到头
开发语言·javascript·ecmascript·gis·webgl·材质·cesium