2026/9/6 7:45:52
网站建设
项目流程
指针 & 引用
| 特性 | 引用 (Reference) | 指针 (Pointer) |
|---|
| 本质 | 变量的别名(语法糖,底层通常就是指针实现) | 存储内存地址的独立变量 |
| 初始化 | 必须在定义时初始化绑定对象 | 定义时可以不初始化(但建议初始化为nullptr) |
| 绑定关系 | 绑定关系不可变更(终身绑定到初次初始化的对象) | 可以随时修改指向新的内存地址 |
| 空值安全性 | 语法上不能为 null(始终假设绑定有效对象) | 可以为nullptr,使用前必须判空(如if(p)) |
| 语法与解引用 | 自动隐式解引用,直接像普通变量一样使用 | 必须通过*p或p->显式解引用访问 |
| 内存占用 | 局部位优化为 0 开销;作为参数/成员时占 4/8 字节 | 占用固定的指针尺寸(32位系统占 4 字节,64位系统占 8 字节) |
| 悬垂风险 | 无空指针风险,但若绑定的对象提前析构,依然会产生悬垂引用 | 存在空指针、野指针以及悬垂指针风险 |
| 典型用途 | 函数参数传递(避免拷贝且语法简洁)、运算符重载 | 动态内存管理(new/delete)、多级指针、可选参数(传nullptr表示无值) |
- 引用的绑定关系(指向)不可改变”,但“被引用对象内部的值”是可以修改的(除非是
const引用)
左值右值
- 当一个右值被绑定到右值引用形参(
T&& arg)上时,在函数内部,这个形参arg自身就变成了左值 - 左值(Lvalue):有变量名、生命周期持久,可以通过 & 获取内存地址(如变量名、解引用 *p、返回引用的函数)
- 右值(Rvalue):无变量名、临时存在(即将销毁),无法直接取地址(如字面量 42、临时对象 std::string(“a”)、返回非引用的函数)
inta=10;// a 是左值intx=10+20;// 10 + 20 是右值std::string s="hello";// "hello" 是右值
左值引用 & 右值引用
| 特性 | 左值引用 (T&) | 右值引用 (T&&) |
|---|
| 绑定对象 | 只能绑定左值(const T&除外,可绑右值) | 只能绑定右值(临时对象、std::move的返回值) |
| 核心用途 | 避免函数传参/返回时的深拷贝 | 资源窃取(移动语义)与完美转发 |
| 内存与身份 | 绑定后继续作为左值使用 | 绑定的形参在函数内部会变成左值(因为有了名字) |
| 典型示例 | int a = 10; int& ref = a; | int&& rref = 42; |
右值引用的使用
移动语义(偷取资源)
std::vector<int> v1 = {1, 2, 3}; // std::move(v1) 将 v1 强转为右值,触发 vector 的移动构造函数 std::vector<int> v2 = std::move(v1); // v2 偷走 v1 的堆内存,0 拷贝!
完美转发(保持原始属性)
template<typename T> void wrapper(T&& arg) { // T&& 此时是万能引用(Universal Reference) // std::forward 确保传入的是右值就按右值转发,左值就按左值转发 target(std::forward<T>(arg)); }