C++ 引用
C++ 引用
Section titled “C++ 引用”C++ 中的引用 (reference) 是现有变量的别名 (alias),即另一个名称。一旦引用被初始化以引用某个变量,你就可以使用变量的名称或引用的名称来访问或修改该变量的值。
可以将其想象成给某人起一个昵称。昵称指的是同一个人。
在 C++ 中创建引用 (Creating References in C++):
Section titled “在 C++ 中创建引用 (Creating References in C++):”你通过在类型和引用名称之间使用符号 (ampersand) (&) 来声明引用变量。至关重要的是,引用在声明时必须初始化,并且必须用一个现有变量(左值 - lvalue)进行初始化。
int originalValue = 10;
// 声明 'ref' 为 'originalValue' 的引用int& ref = originalValue;
// 现在 'ref' 是 'originalValue' 的别名
std::cout << "原始值: " << originalValue << std::endl; // 输出: 10std::cout << "引用值: " << ref << std::endl; // 输出: 10
// 通过引用修改会改变原始变量ref = 25;
std::cout << "修改后的原始值: " << originalValue << std::endl; // 输出: 25std::cout << "修改后的引用值: " << ref << std::endl; // 输出: 25
// 修改原始变量也会改变引用所引用的对象originalValue = 50;std::cout << "原始变量修改后的引用值: " << ref << std::endl; // 输出: 50C++ 引用 vs. 指针 (C++ References vs. Pointers):
Section titled “C++ 引用 vs. 指针 (C++ References vs. Pointers):”引用和指针都允许间接访问变量,但它们之间存在关键区别:
| 特性 (Feature) | 引用 (&) (References (&)) | 指针 (*) (Pointers (*)) |
|---|---|---|
| 初始化 (Initialization) | 声明时必须初始化。 | 可以声明时不初始化,或者稍后初始化。 |
| 可空性 (Nullability) | 不能为 null。必须始终引用一个有效的对象。 | 可以是 nullptr(或者历史上是 NULL),表示它不指向一个有效的对象。 |
| 再赋值/重定向 (Reassignment / Reseating) | 初始化后不能改变以引用不同的变量。 | 可以随时改变以指向不同的变量(或 nullptr)。 |
| 语法 (Syntax) | 使用点运算符 (.) 访问引用对象的成员(如果是类/结构体)。行为类似于原始变量。 | 使用箭头运算符 (->) 通过指针访问成员(或者先解引用 * 再使用 .)。需要解引用 (*) 来获取值。 |
| 地址 (Address) | 通常没有自己独立的内存地址(常被编译器优化掉)。 | 有自己的内存地址,存储着指向的变量的地址。 |
引用作为函数参数 (References as Function Parameters):
Section titled “引用作为函数参数 (References as Function Parameters):”引用的一个主要用途是将参数按引用传递给函数。这允许函数直接修改原始参数,而无需复制的开销。
#include <iostream>
// 函数通过引用接受一个整数void increment(int& num) { // 注意 '&' num++; // 修改作为参数传递的原始变量}
// 函数通过 const 引用接受一个整数(避免复制,阻止修改)void printValue(const int& val) { // 注意 'const' 和 '&' std::cout << "值: " << val << std::endl; // val++; // 编译错误:不能修改 const 引用}
int main() { int counter = 5;
printValue(counter); // 通过 const 引用传递(无复制) increment(counter); // 通过引用传递 printValue(counter); // 查看更新后的值
return 0;}输出 (Output):
Value: 5Value: 6使用 const& 对于将大型对象(如字符串或自定义类)传递给函数,并且只需要读取权限时非常常见。它避免了复制对象的成本,同时保证函数不会改变它。
引用作为返回值 (References as Return Values):
Section titled “引用作为返回值 (References as Return Values):”函数也可以返回引用。这种情况不太常见,但在某些情况下很有用,例如运算符重载(如赋值运算符或 [] 运算符)或从容器返回元素时。
但是,永远不要返回局部变量的引用,因为局部变量在函数结束时将不再存在。这会导致悬垂引用 (dangling reference),从而引发未定义行为。
#include <vector>#include <iostream>
// 示例:函数返回 vector 中元素的引用// (为简单起见,假设索引有效)int& getElement(std::vector<int>& vec, size_t index) { return vec[index]; // 返回 vector 中元素的引用}
/*// 危险:不要这样做!int& badReturn() { int localVar = 10; return localVar; // 返回 localVar 的引用,该变量在函数退出时被销毁!}*/
int main() { std::vector<int> numbers = {10, 20, 30};
// 获取第二个元素(索引 1)的引用 int& numRef = getElement(numbers, 1);
std::cout << "索引 1 处的元素: " << numRef << std::endl; // 输出: 20
// 通过返回的引用修改元素 numRef = 25;
std::cout << "修改后索引 1 处的元素: " << numbers[1] << std::endl; // 输出: 25
// int& dangling = badReturn(); // 危险! // std::cout << dangling << std::endl; // 未定义行为!
return 0;}右值引用 (Rvalue References) (C++11):
Section titled “右值引用 (Rvalue References) (C++11):”C++11 引入了右值引用 (rvalue references)(使用 && 声明)。它们主要绑定到临时对象(右值),并且是移动语义 (move semantics) 和完美转发 (perfect forwarding) 的基础,这些是用于优化资源管理和编写泛型代码的高级技术。