跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

C++ 入门:引用、内联函数与 C++11 新特性详解

C++ 引用别名机制与指针区别,内联函数空间换时间原理及限制,C++11 auto 类型推导规则与场景,基于范围的 for 循环迭代条件,以及 nullptr 解决 NULL 歧义的优势。涵盖参数传递效率对比、返回值风险及编译器优化细节。

SqlMaster发布于 2026/3/21更新于 2026/5/86 浏览
C++ 入门:引用、内联函数与 C++11 新特性详解

一、引用

1. 引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名。编译器不会为引用开辟新的内存空间,它和引用的变量共用同一块内存。

void TestRef() {
    int a = 10;
    int& ra = a; // 定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}

注意:引用类型必须和引用实体是同种类型的。

2. 引用特性
  • 定义时必须初始化。
  • 一个变量可以有多个引用。
  • 引用一旦绑定一个实体,不能再指向其他实体(后续赋值是修改值,而非改变指向)。
#include <iostream>
using namespace std;
int main() {
    int a = 10;
    // int& ra; // 编译报错:必须初始化引用
    
    int& b = a;
    int& d = a; // 一个变量可以有多个引用
    
    int c = 20;
    b = c; // 这里并非让 b 引用 c,而是将 c 的值赋给 b 所指的 a
    return 0;
}
3. 常引用

const 修饰的引用即常引用。当常引用绑定临时变量时,会延长临时变量的生命周期,使其与常引用的生命周期一致。

4. 使用场景

引用做参数: 避免大对象拷贝,提高效率。形参和实参指向同一实体,不用担心值拷贝问题。

void Swap(int& left, int& right) {
    int temp = left;
    left = right;
    right = temp;
}

引用做返回值: 返回局部变量的引用是危险的,因为局部变量出函数后销毁,会导致悬空引用。正确做法是返回静态区变量或全局变量。

// 错误示例:返回局部变量引用
int& Add(int a, int b) {
    int c = a + b;
    return c; // 危险!c 销毁后 ret 成为野指针
}

// 正确示例:返回静态变量引用
int& Count() {
    static int n = 0;
    n++;
    return n;
}

返回引用的优势在于避免对象拷贝(尤其对大对象),提升性能,并支持链式操作。但需警惕被引用对象销毁后的未定义行为。

5. 传引用与传值效率比较

以值作为参数或返回值,期间会产生临时拷贝,效率低下,尤其是大对象。通过代码测试对比传引用和传值的耗时差异,能直观感受到引用在性能上的优势。

#include <time.h>
struct A {
    int a[10000];
};

void TestFunc1(A a) {} // 传值
void TestFunc2(A& a) {} // 传引用

void TestRefAndValue() {
    A a;
    size_t begin1 = clock();
    for (size_t i = 0; i < 1000000; ++i) TestFunc1(a);
    size_t end1 = clock();

    size_t begin2 = clock();
    for (size_t i = 0; i < 1000000; ++i) TestFunc2(a);
    size_t end2 = clock();

    cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
    cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

运行结果通常显示传引用耗时显著更低。

6. 指针和引用的区别

语法上,引用是别名,无独立空间;指针存储地址。底层实现上,引用可能按指针方式实现,但语义不同。

特性引用指针
定义要求必须初始化无要求
重新绑定不可变可变
NULL无 NULL 引用有 NULL 指针
sizeof引用类型大小地址空间大小
多级无多级引用有多级指针
访问自动解引用需显式解引用

引用比指针更安全,不易出错。

二、内联函数

1. 什么是内联函数

以 inline 修饰的函数,编译器会在调用处展开函数体,消除函数调用的栈帧开销,从而提升运行效率。

2. 如何判断是否为内联函数

查看编译器生成的汇编代码中是否存在 call 指令。若没有直接替换为代码,则说明未被内联。Debug 模式下默认不优化,Release 模式更容易观察到内联效果。

3. 内联函数特性

核心是以空间换时间。编译器仅处理规模小、非递归、频繁调用的函数。声明定义通常建议分离,否则可能导致链接错误。内联函数具有内部链接属性,不同源文件可定义同名内联函数而不冲突。

常见问题:

  • 目标文件变大? 是的,因为函数体在多处复制。
  • 递归不能内联? 编译器无法在编译期确定递归展开次数,故不支持。

三、auto 关键字 (C++11)

1. auto 简介

C++11 中 auto 用于编译期类型推导。不再表示'自动存储期',而是根据初始化表达式自动推断变量类型。极大简化了复杂类型(如迭代器、模板)的声明。

核心要求: 变量必须初始化,否则编译器无法推导。

int a = 10;
auto b = a; // 推导为 int
auto c = 'c'; // 推导为 char
2. 使用细则

结合指针和引用:

  • auto* p = &x; 和 auto p = &x; 均推导为指针类型。
  • auto& r = y; 推导为引用类型;若不加 &,则推导为值类型。

多变量定义: 同一行定义的多个变量必须能被推导为相同类型。

auto a = 10, b = 20; // 正确,均为 int
// auto c = 10, d = 3.14; // 错误,类型不一致
3. 不能推导的场景
  • 函数参数: 编译器无法在编译期知道调用时的实际类型。
  • 数组声明: 无法直接推导数组类型,需配合指针或引用。

四、基于范围的 for 循环 (C++11)

1. 语法

由冒号分为迭代变量和被迭代范围两部分,替代传统下标或指针遍历。

int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array) e *= 2; // 修改原值
for(auto e : array) cout << e << " "; // 拷贝遍历
2. 使用条件
  • 范围确定: 数组或提供 begin()/end() 方法的类对象。
  • 支持迭代器: 对象需实现 ++ 和 == 操作。

注意:传递数组指针时,范围 for 无法获取长度,需谨慎使用。

五、指针空值 nullptr (C++11)

1. NULL 的问题

NULL 本质是宏,可能被定义为 0 或 (void*)0。在函数重载时,f(NULL) 可能因歧义导致匹配错误。

2. 引入 nullptr 的原因
  • 明确性: 专门表示指针空值,解决 NULL 的类型歧义。
  • 无需头文件: 关键字级别支持。
  • 类型安全: 可隐式转换为任何指针类型,但不能转为整数。
void f(int);      void f(int*);
f(0);             // 调用 f(int)
f(nullptr);       // 明确调用 f(int*)
3. nullptr 类型

类型为 std::nullptr_t,兼容所有指针类型,但不兼容整数类型。相比 NULL,它能显著提升代码健壮性。

目录

  1. 一、引用
  2. 1. 引用概念
  3. 2. 引用特性
  4. 3. 常引用
  5. 4. 使用场景
  6. 5. 传引用与传值效率比较
  7. 6. 指针和引用的区别
  8. 二、内联函数
  9. 1. 什么是内联函数
  10. 2. 如何判断是否为内联函数
  11. 3. 内联函数特性
  12. 三、auto 关键字 (C++11)
  13. 1. auto 简介
  14. 2. 使用细则
  15. 3. 不能推导的场景
  16. 四、基于范围的 for 循环 (C++11)
  17. 1. 语法
  18. 2. 使用条件
  19. 五、指针空值 nullptr (C++11)
  20. 1. NULL 的问题
  21. 2. 引入 nullptr 的原因
  22. 3. nullptr 类型
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • OpenClaw.ai:Agentic AI 时代的 Spring Framework 时刻
  • 初识 Linux:文件系统预备知识
  • 企业级私有化 AI 部署:从大模型原理到本地智能机器人实战
  • 一周烧光 14 亿 Token!OpenClaw 架构设计的 10 条血泪教训
  • set 与 map 底层实现及高频算法实战
  • Android 常用数据结构原理与性能分析
  • 30 岁转行网络安全:可行性与职业发展深度解析
  • ExtJS 表单控件:单选框与复选框组合使用示例
  • AI 大模型与传统算法的核心差异与类比解析
  • DeepSeek-R1 本地部署指南与语音功能实现
  • 豆包·图像创作模型 Seedream 4.0 多图融合功能体验与评测
  • Trae、Cursor、Copilot、Windsurf AI 编程工具深度对比
  • SeaweedFS 分布式文件系统集群部署指南
  • VSCode 禁用 GitHub Copilot 功能
  • 基于 Linphone 的 Android 音视频通话开发实战
  • 新能源集控系统数据库架构实践:时序数据与高可用设计
  • HarmonyOS Next DevEco Studio 构建配置指南:多目标产物定制
  • PyCharm 安装与配置完整指南
  • 使用 OpenClaw 配置 Codex 5.3 搭建个人 AI 编程助手
  • OpenClaw 接入腾讯 QQ 开放平台实战:一键部署 5 个 AI 机器人

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online