引用(reference)是已存在对象的别名:声明时必须绑定到对象,之后对引用的操作即对原对象的操作。引用不可重新绑定到其他对象,且不能为空(左值引用语义)。C++ 常用引用传递大对象或需要修改形参的场景,语法比指针更简洁。本节在指针基础上说明左值引用、const 引用及与指针的差异。

引用的含义

若 int& ref = n;,则 ref 与 n 表示同一存储单元,不占用额外空间保存副本(实现上可能用地址,但语言层面是别名)。未初始化的引用非法,编译器会报错。

基本用法

#include <iostream>

int main() {
    int n = 5;
    int& ref = n;
    ref = 10;
    std::cout << n << "\n";
    return 0;
}

典型输出:10。对 ref 赋值即修改 n。

引用与指针的语法对比

操作引用指针
声明并绑定int& r = x;int* p = &x;
访问对象r*p
重新绑定不允许p = &y; 允许
空值无nullptr

引用形参

按引用传递可避免拷贝大对象,并允许函数修改实参:

C++ 引用形参交换运行
#include <iostream>

void swap_int(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int x = 1, y = 2;
    swap_int(x, y);
    std::cout << x << " " << y << "\n";
    return 0;
}

典型输出:2 1。调用处写法与按值传递相同,无需写 & 或 *。

const 引用

const T& 承诺不通过该引用修改对象,可绑定到临时量并延长其生命周期至引用所在作用域结束(延长规则仅适用于 const 引用绑定临时量,不宜依赖其做复杂设计):

void print(const std::string& s) {
    std::cout << s.size() << "\n";
}

int main() {
    print("hello");   // 临时 string 可绑定到 const 引用
    return 0;
}

只读遍历容器时常写 const auto&,见范围 for。需要修改时使用非 const 引用。

引用与指针对比

特性引用指针
是否可为空否(std::reference_wrapper 等属特例)可 nullptr
重新绑定否可改指向
语法与对象相同需 *、->
多级无 int&& 左值引用叠用可有 int**
sizeof得到被引用对象类型的大小得到指针本身大小

返回引用

函数可返回引用,但不得返回局部变量的引用或指针:函数结束后局部对象销毁,引用悬垂。合法情形包括:返回参数引用、静态存储期对象、或类成员引用。

int& bad() {
    int local = 0;
    return local;   // 悬垂引用,未定义行为
}

返回容器元素引用时,须保证容器在调用方使用期间仍然存活,例如由调用方拥有的 std::vector。

引用与指针的选用

  • 默认传参:大对象或不可拷贝类型用 const T&;需要可选参数或重绑定用指针并判空。
  • 与 C 接口:C API 多用指针;C++ 封装层可将引用转为内部指针。
  • 成员:类可含引用成员,但须在构造函数初始化列表中绑定,且对象寿命须覆盖引用所绑对象。

右值引用(预告)

C++11 引入右值引用 T&&,用于移动语义与完美转发,见移动语义。本节左值引用是日常传参与别名的基础。

本节说明了引用的别名语义、const 引用与参数传递。下一节介绍new 与 delete:在自由存储区分配对象。