前言
在上一篇文章中,我们学习了 C++ 的输入输出、缺省参数以及函数重载。本文将继续学习 C++ 的其他基础知识,包括引用、inline 内联函数以及 nullptr。
一、引用
1.1 引用的概念和定义
引用不是定义一个新变量,而是给已经存在的变量起一个别名。编译器不会为别名重新开辟空间,它和引用变量共同使用同一块内存。例如将土豆称为马铃薯,番茄称为西红柿,本质是同一个东西。
语法如下:
类型& 别名 = 变量
使用方法:
int a = 10;
int& num = a;
此时 num 就是 a 的新名字,值也为 10。注意在 C++ 引用中,& 的含义是给变量起别名,而非取地址。
1.2 引用的三个特性
1.2.1 引用在定义时必须初始化
在使用引用时,必须先有被引用对象,不能在没有被引用对象的情况下使用引用。
#include<iostream>
using namespace std;
int main() {
int a = 10;
int& num = a; // 正确,已有被引用对象 a
// int& num; // 错误,未初始化
return 0;
}
1.2.2 一个变量可以有多个引用
一个变量可以有一个或多个别名。
#include<iostream>
using namespace std;
int main() {
int a = 10;
int& num1 = a;
int& word = a;
int& word2 = word;
cout << &a << endl;
cout << &num1 << endl;
cout << &word << endl;
cout << &word2 << endl;
return 0;
}
运行结果显示它们的地址相同,说明一个变量确实可以有多个别名。
1.2.3 引用只能引用一个实体
当一个变量被引用产生了一个新的别名,该别名只能用于这个变量,不能再去引用其他变量。
#include<iostream>
using namespace std;
int main() {
int b = 10;
int a = 20;
int& num1 = b;
// int& num1 = a; // 报错,重复定义
return 0;
}
总结:引用必须在定义时就绑定到某个变量,不能先定义后绑定。一个变量可以有多个引用,但一个引用只能绑定到一个变量,且绑定后不能再指向其他变量。
1.3 引用的使用
引用的作用主要是用在函数传参和传返回值。C 语言通过拷贝实参传入形参,数据量大时效率低且存在空指针风险。引用解决了这类问题。
场景 1:函数传参
使用引用传参可以避免拷贝,直接操作原变量。
#include<iostream>
using namespace std;
void Swap(int& x, int& y) {
int temp = x;
x = y;
y = temp;
}
int main() {
int a = 10;
int b = 20;
Swap(a, b);
return 0;
}
场景 2:链表操作
在单链表中,修改头节点通常需要使用二级指针。使用引用可以简化代码。
#include<iostream>
using namespace std;
typedef struct ListNode {
struct ListNode* next;
int val;
}ListNode;
void Push_elem_front(ListNode*& head_of_List, int elem) {
// 逻辑实现
}
这里 head_of_List 是 phead 的别名,无需二级指针即可修改头节点指向。
场景 3:返回值
返回引用可以直接修改节点的值。
int& getNodeVal(ListNode* phead, int pos) {
// 查找逻辑
return pcur->val;
}
// 调用:getNodeVal(phead, pos) = 200;
注意:不能返回局部临时变量的引用,因为函数结束后内存会被回收,导致悬空引用。
1.4 const 引用
作用 1:防止变量被修改
int a = 10;
const int& num = a;
// num = 100; // 错误
作用 2:效率优化
传递大型结构体时使用 const 引用可避免拷贝开销。
typedef struct { int arr[1000]; } BigStruct;
void read(const BigStruct& s) {}
作用 3:隐式类型转换
double a = 3.14;
const int& b = a; // 允许隐式转换
1.5 引用和指针的关系
指针和引用各有特点,不可替代。
- 引用是别名,不开空间;指针存储地址,开空间。
- 引用必须初始化,指针建议初始化。
- 引用初始化后不可改指向,指针可以。
- 引用直接访问,指针需解引用。
- sizeof 含义不同。
- 指针易出现空指针/野指针,引用更安全。
二、inline 内联函数
被 inline 修饰的函数叫内联函数。编译时编译器会在调用处直接展开代码,不建立额外栈帧,提高效率。
#include<iostream>
using namespace std;
inline int add(int a, int b) {
return a + b;
}
内联函数是对 C 语言宏的改进,宏容易出错且难调试。inline 由编译器控制是否展开,若代码复杂或递归,编译器可能忽略 inline 建议。
注意:inline 不建议声明和定义分离到两个文件,否则会导致链接错误。
三、nullptr
NULL 是宏,在 C 和 C++ 下含义不同。C++ 中 NULL 定义为 0,可能导致函数重载歧义。
void f(int x) {}
void f(int* x) {}
int main() {
f(0); // 调用 f(int)
f(NULL); // 调用 f(int)
f(nullptr);// 调用 f(int*)
}
nullptr 是 C++11 引入的关键字,专门用于空指针初始化,意义统一,推荐使用。

