Skip to content

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; // 输出: 10
std::cout << "引用值: " << ref << std::endl; // 输出: 10
// 通过引用修改会改变原始变量
ref = 25;
std::cout << "修改后的原始值: " << originalValue << std::endl; // 输出: 25
std::cout << "修改后的引用值: " << ref << std::endl; // 输出: 25
// 修改原始变量也会改变引用所引用的对象
originalValue = 50;
std::cout << "原始变量修改后的引用值: " << ref << std::endl; // 输出: 50

C++ 引用 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: 5
Value: 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;
}

C++11 引入了右值引用 (rvalue references)(使用 && 声明)。它们主要绑定到临时对象(右值),并且是移动语义 (move semantics) 和完美转发 (perfect forwarding) 的基础,这些是用于优化资源管理和编写泛型代码的高级技术。