15. 引用:引用概念、引用与指针区别、引用作为函数参数

引用这个话题,说实话是很多C++初学者容易「卡住」的地方。我记得自己刚学那会儿,总觉得引用和指针差不多,干嘛要搞两个东西出来?后来在项目里踩了几次坑,才真正体会到——引用这东西,用好了是真香。

引用的基本概念

引用,说白了就是给一个变量起个「别名」。你想想看,一个人有大名也有小名,叫哪个都是在叫同一个人。引用也是这个道理。

int a = 10;
int& ref = a;   // ref 是 a 的引用
ref = 20;        // 实际上修改的是 a
cout << a;      // 输出 20

这里有个关键点:引用必须在定义时初始化,而且一旦绑定到某个变量,就不能再改绑到别的变量上。这一点和指针很不一样。

核心要点:引用就是变量的别名,操作引用就是操作原变量本身。

引用与指针的区别

很多初学者会问:引用和指针到底有什么区别?我建议你从这几个维度去理解:

对比维度 引用 指针
初始化 必须初始化,不能为空 可以不初始化,可以为空
重新绑定 不能改绑 可以指向不同对象
内存占用 不额外占用(编译器优化) 占用指针大小的内存
语法操作 像普通变量一样使用 需要解引用 * 操作
空值风险 不存在空引用 可能为 nullptr,需检查

我在项目中遇到过这样一个场景:有个同事用指针传参,结果忘了检查空指针,程序直接崩了。后来改成引用,这种问题就再也没出现过。嗯,这就是引用的一个好处——天生安全

我的建议:能用引用就别用指针。引用更安全,语法也更简洁。只有在需要「重新指向」或者「可能为空」的场景下,才考虑用指针。

引用作为函数参数

引用最常见的用途就是作为函数参数。为什么要用引用传参?说白了就两个原因:避免拷贝修改实参

1. 避免拷贝,提升性能

// 值传递:会拷贝整个对象
void processValue(string s) {
    // 操作 s
}

// 引用传递:没有拷贝,直接操作原对象
void processRef(string& s) {
    // 操作 s
}

你想想看,如果传的是一个很大的结构体或者类对象,值传递会触发拷贝构造函数,性能开销可不小。引用传递就只是传了个别名,几乎没有开销。

2. 修改实参

void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int x = 5, y = 10;
swap(x, y);  // x 变成 10,y 变成 5

这个例子很经典。如果不传引用,swap 函数里改的只是副本,外面的 x 和 y 纹丝不动。传引用才能「动真格」的。

3. const 引用:只读不写

void printData(const vector<int>& data) {
    for (int v : data) {
        cout << v << " ";
    }
    // data.push_back(100);  // 编译错误!const 引用不能修改
}

const 引用是个好东西。它既避免了拷贝,又保证了函数内部不会意外修改实参。我个人习惯是:只要不需要修改参数,一律用 const 引用

注意:不要返回局部变量的引用!局部变量在函数结束后就销毁了,返回它的引用会导致悬空引用,程序行为未定义。

// 错误示例
int& badFunction() {
    int local = 42;
    return local;  // local 已销毁,返回的是悬空引用
}

引用与右值引用

C++11 引入了右值引用(&&),这又是另一个话题了。简单提一句:右值引用主要用于移动语义和完美转发,能进一步提升性能。不过初学者先掌握左值引用就够了,右值引用后面再深入。

知识体系图

下面这张图帮你梳理了引用的核心知识脉络:

C++ 引用 基本概念 变量的别名 必须初始化 不能改绑 与指针区别 引用更安全 语法更简洁 无空值风险 函数参数 避免拷贝 修改实参 const 引用 核心原则:能用引用就用引用, 需要重新指向或可能为空时才用指针

避坑指南

最后分享几个我踩过的坑:

  • 我曾经在写代码时把引用和取地址符 & 搞混了。记住:int& ref = a; 是引用,int* ptr = &a; 是取地址。
  • 我曾经在函数里返回了局部变量的引用,结果程序跑着跑着就崩了。从那以后,我每次写返回引用都会多看一眼——是不是返回了栈上的东西。
  • 我建议新手先别碰右值引用,先把左值引用用熟。基础打牢了,后面学移动语义才不费劲。

引用这个东西,用多了就习惯了。你只要记住:引用就是别名,操作引用就是操作原变量,大部分场景都能想明白。

公众号:蓝海资料掘金营,微信 deep3321