【C++】const引用、inline、nullptr三大语法
·
📌 相关文章推荐
很高兴你点开这篇文章✨
这里会持续更新我喜欢的内容,关注我,一起慢慢变好呀
👍 点赞 ⭐ 收藏 💬 评论
文章目录
前言
学完引用之后,你是否也和我一样有疑问:const 引用是什么?什么时候用?还有,C++ 里怎么定义常量?NULL 和 nullptr 到底有什么区别?
下面我们就一起来探讨这些问题吧!
一、const 引用
1.1 什么是 const 引用?
const 引用就是只读的引用。你可以通过它读取数据,但不能通过它修改数据。
int a = 10;
const int& r = a; // r 是 a 的 const 引用
// r = 20; // ❌ 报错:不能通过 const 引用修改
a = 20; // ✅ 但可以通过原变量修改
1.2 const 引用的三大特性
| 特性 | 说明 |
|---|---|
| 可读不可写 | 不能通过 const 引用修改值 |
| 可以绑定常量 | const int& r = 10; 合法 |
| 可以绑定临时对象 | 函数返回的临时值也能绑定 |
比如:
const int& r1 = 10; // ✅ 绑定常量
const int& r2 = a + b; // ✅ 绑定表达式结果(临时对象)
1.3 权限的三种情况(非常重要)
C++ 中引用传递权限只能平移或缩小,不能放大。
| 情况 | 原变量权限 | 引用权限 | 是否允许 |
|---|---|---|---|
| 平移 | 可读可写 | 可读可写 | 是 |
| 缩小 | 可读可写 | 只读(const) | 是 |
| 放大 | 只读(const) | 可读可写 | 禁止 |
示例:
//权限平移---普通变量->普通引用,权限不变,都是可读可写
int a=10; a:可读可写
int& ra=a; ra:可读可写
//权限缩小---普通变量->const引用,把“可写”的权限收回去,变成只可读
int a=10; a:可读可写
const int& ra=a; ra:只能读
//权限放大---const引用->普通引用,想把只读变成可写,违法!
const int a=10; a:只可读
int& ra=a; ra:想又可读又可写,绝对不可以!
1.4 const 引用的典型应用:函数参数
void print(const int& x)
{
// x 是只读的,不会意外修改外面的值
// 同时避免了拷贝,效率高
cout << x << endl;
}
🐾 为什么用 const 引用传参?
- 避免拷贝(大对象时效率高)
- 保证不修改原数据(安全)
- 可以接收常量和临时对象(灵活)
🐶 🐾 ✨ 🐾 🐶
二、inline 内联函数
2.1 为什么需要 inline?
C 语言中用宏(#define)来定义小函数,但宏有很多坑:
#define ADD(a, b) ((a) + (b)) // 必须加一堆括号,很麻烦
🐾 C++ 提供了 inline 关键字,用来建议编译器把函数调用展开成代码,消除函数调用的开销。
inline int add(int a, int b)
{
return a + b;
}
int ret = add(1, 2); // 编译后可能直接变成 int ret = 1 + 2;
2.2 inline 的特点
| 特点 | 说明 |
|---|---|
| 建议性 | inline 只是给编译器的建议,是否展开由编译器决定 |
| 适合短小函数 | 函数体太长,编译器会忽略 inline |
| 不能递归 | 递归函数无法内联展开 |
| 声明和定义不能分离 | 通常直接写在头文件里 |
2.3 宏 vs inline
| 对比项 | 宏(#define) | inline 函数 |
|---|---|---|
| 类型检查 | 没有 | 有 |
| 调试支持 | 不可调试 | 可调试 |
| 作用域 | 全局预处理器 | 遵循 C++ 作用域规则 |
| 参数求值 | 可能多次求值 | 正常求值一次 |
宏的问题示例:
#define SQUARE(x) ((x) * (x))
int a = 2;
int b = SQUARE(++a); // 展开后:(++a) * (++a) -> a 被加了两次!
// inline 函数不会有这个问题
inline int square(int x)
{
return x * x;
}
int c = square(++a); // 正常,a 只加一次
三、nullptr 空指针
3.1 问题的由来:NULL 是什么?
在 C++ 中,NULL 通常被定义为 0 或 (void*)0,这会导致函数重载的二义性问题。
void f(int x)
{
cout << "f(int x)" << endl;
}
void f(int* ptr)
{
cout << "f(int* ptr)" << endl;
}
int main()
{
f(0); // 调用 f(int)
f(NULL); // 调用 f(int) 还是 f(int*)?大多数情况是 f(int)
f((int*)NULL); // 强制转成指针,才能调用 f(int*)
}
🐾 问题:NULL 会被当成整数 0,而不是指针,导致调错函数。
3.2 nullptr 的解决方案
C++11 引入了 nullptr,它是类型安全的空指针。
f(nullptr); // 明确调用 f(int*),不会混淆
| 对比项 | NULL | nullptr |
|---|---|---|
| 类型 | 整数(通常是 0) | std::nullptr_t |
| 是否可转成整数 | 可以 | 不可以隐式转 |
| 是否可转成指针 | 可以(但会二义) | 可以 |
| 函数重载 | 可能调错 | 总能正确匹配指针版本 |
3.3 nullptr 的使用
int* p1 = NULL; // 能用,但不推荐
int* p2 = nullptr; // 推荐
char* p3 = nullptr; // 可以转成任何指针类型
// int a = nullptr; // ❌ 不能转成整数
// 判断空指针
if (p2 == nullptr)
{
cout << "p2 is null" << endl;
}
🐾 建议一律使用 nullptr,不要再用 NULL!!
四、知识点汇总
| 知识点 | 核心要点 |
|---|---|
| const 引用 | 只读引用,可绑常量和临时对象,权限只能缩小不能放大 |
| const 引用传参 | 避免拷贝 + 只读保护 + 灵活接收常量 |
| inline | 建议编译器展开函数,消除调用开销,适合短小函数 |
| inline vs 宏 | inline 有类型检查、可调试、更安全 |
| nullptr | 类型安全的空指针,解决 NULL 的重载二义性 |
五、常见面试题
🐾 Q1:const int& 能绑定到 int 变量吗?能绑定到 int 常量吗?
int a = 10;
const int& r1 = a; // 能
const int& r2 = 20; // 能
🐾 Q2:inline 函数一定能内联成功吗?
- 不一定。inline 只是建议,编译器对长函数、递归函数通常会忽略。
🐾 Q3:nullptr 的类型是什么?
- std::nullptr_t ,可以隐式转换成任何指针类型,但不能转成整数。
🐶 🐾 ✨ 🐾 🐶
谢谢你看到这里呀
如果喜欢这篇内容,点个关注,下次更新不迷路✨
👍 点赞 ⭐ 收藏 💬 评论
更多推荐

所有评论(0)