> 技术文档 > C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!


🔥C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!🔥

  • 函 数 重 载
    • 定 义
    • 条 件
      • 参 数 类 型 不 同
      • 参 数 数 量 不 同
      • 参 数 顺 序 不 同
    • C++ 支 持 函 数 重 载 的 原 因
      • 总 结
  • 引 用
    • 定 义
    • 使 用 方 法
    • 使 用 场 景
    • 传 值、传 引 用 效 率 比 较
    • 引 用 在 顺 序 表 的 应 用
    • 常 引 用
      • 总 结
    • 引 用 和 指 针 的 不 同 点
  • 内 联 函 数
    • 定 义
    • 基 本 语 法
    • 内 联 函 数 VS 宏
    • 核 心 作 用 - - - 减 少 函 数 调 用 开 销
    • 编 译 器 处 理 规 则
  • auto 关 键 字
    • 定 义
    • 基 本 语 法
    • auto 在 数 组 中 的 应 用
    • 范 围 for 循 环 使 用 的 条 件
  • 指 针 空 值(nullptr)
  • 总 结

💻作 者 简 介:曾 与 你 一 样 迷 茫,现 以 经 验 助 你 入 门 数据 结 构。
💡个 人 主 页:@笑口常开xpr 的 个 人 主 页
📚系 列 专 栏:C++ 炼 魂 场:从 青 铜 到 王 者 的 进 阶 之 路
✨代 码 趣 语:在 C++ 里,指 针 是 距 离 硬 件 最 近 的 魔 法,当 然,也 可 能 是 距 离 bug 最 近 的 魔 法。
💪代 码 千 行,始 于 坚 持,每 日 敲 码,进 阶 编 程 之 路。
📦gitee 链 接:gitee

在这里插入图片描述

         C++ 作 为 一 门 兼 容 C 语 言 特 性 且 融 入 现 代 编 程 范 式 的 语 言,是 系 统 开 发 与 高 性 能 应 用 的 重 要 工 具。本 文 聚 焦 其 核 心 基 础 - - - 引 用、函 数 重 载、nullptr、内 联 函 数 和 auto 等 关 键 特 性,帮 你 快 速 掌 握 入 门 要 点,夯 实 基 础,轻 松 应 对 面 试。


函 数 重 载

定 义

         重 载:在 自 然 语 言 中,一 个 词 有 多 种 意 思,可 以 通 过 上 下 文 来 判 断 该 词 真 正 的 意 思。
         函 数 重 载 是 函 数 的 一 种 特 殊 情 况,C++ 允 许 在 同 一 作 用 域 中 声 明 几 个 功 能 类 似同 名 函 数,这 些 同 名 函 数 的 形 参 列 表 ( 参 数 个 数 或 类 型 或 类 型 顺 序 ) 不 同函 数 重 载 对 返 回 值 没 有 要 求,即 函 数 重 载 与 返 回 值 是 否 相 同 没 有 影 响。常 用 来 处 理 实 现 功 能 类 似 数 据 类 型 不 同 的 问 题。


条 件

参 数 类 型 不 同

#include<iostream>using namespace std;void print(int num) { cout << \"void print(int num)\" << endl;}void print(double num) { cout << \"void print(double num)\" << endl;}int main(){ print(1); print(1.1); return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         函 数 参 数 类 型 不 同,函 数 名 字 相 同,构 成 函 数 重 载。编 译 器 会 自 动 匹 配 类 型。


参 数 数 量 不 同

#include<iostream>using namespace std;void sum(int a, int b) { cout << \"void sum(int a, int b)\" << endl;}void sum(int a, int b, int c) { cout << \"void sum(int a, int b, int c)\" << endl;}int main(){ sum(1, 2); sum(1, 2, 3); return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         函 数 参 数 类 型 相 同,函 数 名 字 相 同,参 数 个 数 不 同。构 成 函 数 重 载。编 译 器 会 自 动 匹 配 类 型。
注 意

#include<iostream>using namespace std;void f(){cout << \"f()\" << endl;}void f(int a = 0){cout << \"f(int a = 0)\" << endl;}int main(){f();return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         函 数 名 字 相 同,参 数 个 数 不 同,构 成 函 数 重 载。但 会 报 错,是 因 为 缺 省 参 数 调 用 时 可 以 不 传 参,两 个 函 数 都 可 以,存 在 调 用 歧 义。


参 数 顺 序 不 同

#include<iostream>using namespace std;void process(int a, double b) { cout << \"void process(int a, double b)\" << endl;}void process(double a, int b) { cout << \"void process(double a, int b)\" << endl;}int main(){ process(1, 1.1); process(1.2, 1); return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         函 数 参 数 类 型 相 同,函 数 名 字 相 同,参 数 顺 序 不 同,构 成 函 数 重 载。


注 意
         函 数 重 载 与 函 数 的 返 回 类 型 和 参 数 名 字 是 否 相 同 没 有 关 系。

#include<iostream>using namespace std;void f(int a, char b){cout << \"f(int a, char b)\" << endl;}void f(int b, char a){cout << \"f(int b, char a)\" << endl;}int main(){f(1, \'x\');return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         函 数 参 数 类 型 相 同,函 数 名 字 相 同,函 数 参 数 名 字 不 同,不 构 成 函 数 重 载,程 序 会 报 错。


C++ 支 持 函 数 重 载 的 原 因

         这 里 以 Linux 环 境 为 例 演 示 C 语 言 为 什 么 不 支 持 函 数 重 载,C++ 为 什 么 支 持 函 数 重 载。
1、使 用 mkdir + 空 格 + 文 件 名 创 建 文 件 夹。可 以 使 用 ls 显示 当 前 文 件 夹 中 的 文 件。如 下 图 创 建 的 文 件 夹 为 C。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
2、使 用 cd + 空 格 + 文 件 名 这 条 指 令 可 以 进 入 当 前 文 件 夹。如 下 图 所 示,当 前 文 件 夹 中 没 有 内 容 为 空。 C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
3、使 用 nano + 空 格 + 文 件 名 这 条 指 令 可 以 编 辑 并 创 建 文 件。在 test.c 中 写 的 代 码 如 下 图 所 示。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
4、代 码 完 成 后,按 住 ctrl + x 出 现 如 下 的 页 面,输 入 Y 保 存 文 件 后,按 回 车 退 出 编 辑。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
5、可 以 输 入 cat + 空 格 + 文 件 名 来 查 看 文 件 中 的 内 容。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
6、输 入 gcc + 空 格 + 文 件 名 编 译 C 语 言 文 件,此 时 默 认 生 成 的 可 执 行 程 序 为 a.out。可 以 通 过 gcc + 空 格 + -o + 空 格 + 文 件 名 + 空 格 + test.c 将 生 成 的 可 执 行 程 序 重 命 名。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
7、使 用 objdump + 空 格 + -S + 空 格 + testc 查 看 C 语 言 代 码 的 汇 编 代 码。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
8、在 汇 编 代 码 中 找 到 Func 如 下 图 所 示。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
结 论:在 linux 环 境 下,采 用 gcc 编 译 完 成 后,函 数 名 字 的 修 饰 没 有 发 生 改 变。

9、使 用 cp + 空 格 + 原 文 件 + 空 格 + 新 文 件 复 制 并 重 命 名 原 文 件。C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
10、使 用 nano 指 令 将 test.cpp 中 的 注 释 部 分 删 掉 即 可。C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
11、修 改 后 的 文 件 如 下 图 所 示,然 后 保 存 并 退 出。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
12、和 上 面 的 类 似 使 用 gcc 编 译 并 将 生 成 的 可 执 行 程 序 重 命 名 为 testcpp。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
13、使 用 objdump 这 条 指 令 生 成 汇 编 代 码。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
14、在 生 成 的 汇 编 语 言 中 找 到 Func 函 数。
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!

结 论:在 linux 环 境 下,采 用 g++ 编 译 完 成 后,函 数 名 字 的 修 饰 发 生 改 变,编 译 器 将 函 数 参 数 类 型 信 息 添 加 到 修 改 后 的 名 字 中。


总 结

         C 语 言 没 办 法 支 持 重 载,因 为 同 名 函 数 没 办 法 区 分。而C++ 是 通 过 函 数 修 饰 规 则 来 区 分,只 要 参 数 不 同,修 饰 出 来 的 名 字 就 不 一 样,就 支 持 了 重 载。
         如 果 两 个 函 数 的 函 数 名 和 参 数 是 一 样 的,返 回 值 不 同 是 不 构 成 重 载 的,因 为 调 用 时 编 译 器 没 办 法 区 分。


引 用

定 义

         引 用 是 一 项 重 要 特 性,它 为 变 量 提 供 了 一 个 别 名,让 你 能 够 通 过 这 个 别 名 来 访 问 和 操 作 原 始 变 量。编 译 器 不 会 为 引 用 变 量 开 辟 内 存 空 间,它 和 它 引 用 的 变 量 共 用 同 一 块 内 存 空 间。


使 用 方 法

  1. 引 用 是 已 存 在 变 量 的 别 名,通 过 在 变 量 名 前 使 用 & 符 号 声 明。
  2. 引 用 必 须 在 声 明 时 初 始 化,且 一 旦 初 始 化 后 不 能 再 引 用 其 他 变 量。
  3. 一 个 变 量 可 以 有 多 个 引 用。
  4. 引 用 在 同 一 个 域 不 能 同 名,在 不 同 的 域 可 以 同 名。
#include<iostream>using namespace std;int main(){int a = 0;int& b = a;int& c = b;int& d = a;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;b++;cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;d++;cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!

#include<iostream>using namespace std;int main(){int a = 0;int& d = a;int x = 11;//d变成x的引用还是别名d = x;//赋值cout << x << endl;cout << d << endl;cout << &x << endl;cout << &d << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         在 上 面 的 代 码 中 d = x 是 赋 值,而 不 是 引 用。赋 值 需 要 开 辟 空 间,引 用 是 多 个 变 量 在 同 一 份 空 间。


使 用 场 景

  1. 引 用 传 递 允 许 函 数 直 接 修 改 实 参 的 值,避 免 值 传 递 的 拷 贝 开 销。(输 出 型 参 数
#include<iostream>using namespace std;void Swap(int* a, int* b){int tmp = *a;*a = *b;*b = tmp;}void Swap(int& a, int& b){int tmp = a;a = b;b = tmp;}int main(){int x = 0;int y = 1;cout << x << \" \" << y << endl;//Swap(&x, &y);Swap(x, y);cout << x << \" \" << y << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!


  1. 通 过 引 用 传 递 指 针 与 通 过 指 针 的 指 针 传 递。
#include<iostream>using namespace std;void Swap(int*& a, int*& b){int* tmp = a;a = b;b = tmp;}void Swap(int** a, int** b){int* tmp = *a;*a = *b;*b = tmp;}int main(){int x = 0;int y = 1;int* px = &x;int* py = &y;cout << *px << \" \" << *py << endl;Swap(px, py);cout << *px << \" \" << *py << endl;Swap(&px, &py);cout << *px << \" \" << *py << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!


  1. 通 过 引 用 传 递 头 指 针,确 保 可 以 修 改 原 指 针。
#include<iostream>using namespace std;typedef struct ListNode{struct ListNode* next;int val;}LTNode, *PLTNode;//LTNode == struct ListNode;//PLTNode == struct ListNode*;void ListPushBack(PLTNode& phead, int x){}int main(){PLTNode plist = NULL;ListPushBack(plist, 1);return 0;}

  1. 引 用 做 返 回 值
    传 值 返 回
#include<iostream>using namespace std;int Count(){static int n = 0;n++;return n;//会产生临时变量,关注的是类型}int main(){int ret = Count();cout << ret << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
传 值 返 回 时 一 定 会 生 成 临 时 变 量。


传 引 用 返 回

#include<iostream>using namespace std;int& Count(){static int n = 0;n++;return n;}int main(){int ret = Count();cout << ret << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         传 引 用 返 回 的 是 n 的 别 名,n 的 引 用。不 会 产 生 临 时 变 量。
价 值:减 少 拷 贝,提 高 效 率。
注 意
永 远 不 要 返 回 局 部 变 量 的 引 用 或 指 针。

#include<iostream>using namespace std;int& Count(){int n = 0;n++;//...return n;}int main(){int ret = Count();cout << ret << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         上 面 的 代 码 中,返 回 了 局 部 变 量 的 引 用,即 返 回 了 局 部 变 量 n 的 地 址,但 是 当 函 数 返 回 时 栈 帧 被 销 毁,n 的 内 存 空 间 不 再 有 效,此 时 ret 的 值 是 不 确 定 的。这 是 因 为 Count 函 数 结 束 后,没 有 清 理 栈 帧,ret 的 结 果 侥 幸 是 正 确 的,如 果 清 理 栈 帧,ret 的 结 果 就 是 随 机 值。
         如 果 要 安 全 返 回 则 需 要 谨 慎 使 用 静 态 变 量 、动 态 内 存 分 配 或 者 返 回 值。

总 结

  1. 基 本 任 何 场 景 都 可 以 使 用 引 用 返 回。
  2. 谨 慎 使 用 引 用 做 返 回 值,出 了 函 数 作 用 域,对 象 不 在 了,就 不 能 使 用 引 用 返 回,否 则 还 在,就 可 以 使 用 引 用 返 回。
  3. 命 名 空 间 不 会 影 响 生 命 周 期。

传 值、传 引 用 效 率 比 较

         以 值 作 为 参 数 或 者 返 回 值 类 型,在 传 参 和 返 回 期 间,函 数 不 会 直 接 传 递 实 参 或 者 将 变 量 本 身 直 接 返 回,而 是 传 递 实 参 或 者 返 回 变 量 的 一 份 临 时 的 拷 贝,因 此 用 值 作 为 参 数 或 者 返 回 值 类 型,效 率 是 非 常 低 下 的,尤 其 是 当 参 数 或 者 返 回 值 类 型 非 常 大 时,效 率 就 更 低。
         引 用 做 参 数 可 以 提 高 效 率(大 对 象 / 深 拷 贝 类 对 象)
         大 对 象:大 对 象 通 常 指 占 用 大 量 内 存 或 包 含 动 态 分 配 资 源(如 堆 内 存、文 件 句 柄 等)的 对 象。

#include <time.h>#include<iostream>using namespace std;//C++里结构体可以用A或者struct Astruct 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 < 10000; ++i){TestFunc1(a);}size_t end1 = clock();//以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 10000; ++i){TestFunc2(a);}size_t end2 = clock();//分别计算两个函数运行结束后的时间cout << \"TestFunc1(A)-time:\" << end1 - begin1 << endl;cout << \"TestFunc2(A&)-time:\" << end2 - begin2 << endl;}int main(){TestRefAndValue();return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         TestFunc1 的 耗 时 会 显 著 高 于 TestFunc2,这 是 因 为 值 传 递 需 要 频 繁 复 制 大 对 象,涉 及 大 量 内 存 操 作。而 引 用 传 递 只 需 传 递 指 针,无 需 复 制 数 据。


引 用 在 顺 序 表 的 应 用

#include <assert.h>#include <iostream>using namespace std;typedef struct SeqList{int a[100];int size;}SeqList;int SLGet(SeqList* ps, int pos){assert(pos < 100 && (pos >= 0));return ps->a[pos];}void SLModify(SeqList* ps, int pos, int x){assert(pos < 100 && (pos >= 0));assert(ps);ps->a[pos] = x;}int& SLAt(SeqList* ps, int pos){assert(pos < 100 && pos >= 0);return ps->a[pos];}int& SLAt(SeqList& ps, int pos){assert(pos < 100 && pos >= 0);return ps.a[pos];}int main(){SeqList s;//方法1SLModify(&s, 0, 1);cout << SLGet(&s, 0) << endl;//对第0个位置+5int ret = SLGet(&s, 0);SLModify(&s, 0, ret + 5);//方法2//引用(读写)SLAt(&s, 0) = 1;cout << SLAt(&s, 0) << endl;SLAt(&s, 0) += 5;//方法3SLAt(s, 0) = 1;cout << SLAt(s, 0) << endl;SLAt(s, 0) += 5;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         在 方 法 1 中 如 果 想 要 改 变 某 一 位 置 的 值,需 要 使 用 SLGet 和 SLModify 2 个 函 数,方 法 2 只 需 要 使 用 引 用 做 返 回 值 可 以 修 改 返 回 值。方 法 3 是 对 方 法 2 进 行 了 简 化。


常 引 用

         常 引 用 是 指 向 常 量 对 象 的 引 用。它 的 主 要 作 用 是 在 引 用 对 象 时,禁 止 通 过 该 引 用 对 对 象 的 值 进 行 修 改,从 而 保 证 数 据 的 安 全 性。
1. 情 况 1

#include<iostream>using namespace std;int main(){//不可以//引用过程中,权限不能放大const int a = 0;int& b = a;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         const 的 主 要 功 能 是 对 对 象 的 不 可 变 性 进 行 声 明,即 const 变 量 一 旦 被 初 始 化,其 值 就 不 能 再 被 更 改。引 用 过 程 中 权 限 不 能 放 大。

#include <iostream>using namespace std;int main(){ //方法1 //将引用b也声明为const类型 const int a = 0; const int& b = a; //权限保持一致或缩小 //方法2 //如果需要修改值,就不要使用const int c = 0; int& d = c; //c本身是变量 //方法3 //使用常量引用绑定临时对象 const int& e = 42; //常量引用可绑定临时对象 return 0;}

2. 情 况 2

#include<iostream>using namespace std;int main(){const int c = 0;int d = c;return 0;}

         这 种 情 况 可 以,这 是 赋 值,c 拷 贝 给 d,没 有 放 大 权 限,因 为 d 的 改 变 不 影 响 c。


3. 情 况 3

#include<iostream>using namespace std;int main(){int x = 0;int& y = x;//权限的平移const int& z = x;//缩小z的权限return 0;}

         在 引 用 过 程 中,权 限 可 以 缩 小 或 平 移,但 不 能 放 大。上面 的 代 码 中 因 为 const 修 饰 的 变 量 的 值 不 能 发 生 改 变,所 以 z 不 能 ++,x 可 以 ++。


4. 情 况 4

#include<iostream>using namespace std;int main(){double e = 1.11;//int& rii = e;//产生int的临时变量const int& rii = e;//临时变量具有常性return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!

         上 面 的 代 码 中 发 生 了 隐 式 类 型 转 换,类 型 转 换 产 生 的 临 时 对 象 默认 具 有 常 量 性,因 此 只 能 用 const 引 用 绑 定。
         发 生 类 型 转 换(强 制 类 型 转 换,截 断,隐 式 类 型 转 换),函 数 会 产 生 临 时 变 量。相 同 类 型 不 产 生 临 时 变 量。


5. 情 况 5

#include<iostream>using namespace std;int func1(){static int x = 0;return x;}int& func2(){static int x = 0;return x;}int main(){int ret1 = func1();//拷贝int& ret1 = func1();const int& ret1 = func1();//权限的平移int& ret1 = func2(); //权限的平移const int& ret1 = func2();//权限的缩小return 0;}

         函 数 返 回 的 是 临 时 变 量,临 时 变 量 具 有 常 性。由 传 值 返 回 变 为 引 用,这 是 权 限 的 放 大。


总 结

         在 C++ 中,引 用 的 权 限 不 能 超 过 原 始 对 象 的 权 限。也 就 是 说,不 能 通 过 引 用 去 获 得 比 原 始 对 象 更 多 的 修 改 权 限。常 量 对 象 只 能 被 常 量 引 用,而 变 量 对 象 则 可 以 被 常 量 引 用 或 者 非 常 量 引 用。


引 用 和 指 针 的 不 同 点

  1. 引 用 概 念 上 定 义 一 个 变 量 的 别 名,指 针 存 储 一 个 变 量 地 址。
  2. 引 用 在 定 义 时 必 须 初 始 化,指 针 没 有 要 求。
  3. 引 用 在 初 始 化 时 引 用 一 个 实 体 后,就 不 能 再 引 用 其 他 实 体,而 指 针 可 以 在 任 何 时 候 指 向 任 何
    一 个 同 类 型 实 体。
  4. 没 有 NULL 引 用,但 有 NULL 指 针。
  5. 在 sizeof 中 含 义 不 同:引 用 结 果 为 引 用 类 型 的 大 小,但 指 针 始 终 是 地 址 空 间 所 占 字 节 个 数( 32 位 平 台 下 占 4 个 字 节)
  6. 引 用 自 加 即 引 用 的 实 体 增 加 1,指 针 自 加 即 指 针 向 后 偏 移 一 个 类 型 的 大 小。
  7. 有 多 级 指 针,但 是 没 有 多 级 引 用。
  8. 访 问 实 体 方 式 不 同,指 针 需 要 显 式 解 引 用,引 用 编 译 器 自 己 处 理。
  9. 引 用 比 指 针 使 用 起 来 相 对 更 安 全,但 引 用 不 能 完 全 代 替 指 针。指 针 有 野 指 针 和 空 指 针,但 引 用 没 有。

内 联 函 数

定 义

         内 联 函 数 是 一 种 特 殊 函 数,通 过 编 译 器 优 化 减 少 函 数 调 用 开 销,提 高 执 行 效 率。


基 本 语 法

         使 用 inline 关 键 字 声 明,建 议 编 译 器 将 函 数 体 直 接 替 换 调 用 处(类 似 宏 展 开):

inline int add(int a, int b) { return a + b;}

宏 函 数(C 语 言)
优 点:不 需 要 建 立 栈 帧,提 高 调 用 效 率。
缺 点:复 杂,容 易 出 错,可 读 性 差,不 能 调 试。

#define Add(x, y) (x + y) * 10

内 联 函 数 VS 宏

特 性 内 联 函 数 宏 类型安全 遵循 C++ 类型检查 简单文本替换,无类型检查 调试支持 可调试 不可调试(预处理阶段展开) 副作用 无 可能多次求值 代码膨胀风险 由编译器决定是否展开 强制展开,可能导致代码冗余

核 心 作 用 - - - 减 少 函 数 调 用 开 销

普 通 函 数 调 用 流 程

  1. 保 存 调 用 位 置 上 下 文
  2. 跳 转 到 函 数 地 址 执 行
  3. 返 回 时 恢 复 上 下 文

内 联 函 数:直 接 将 函 数 体 代 码 复 制 到 调 用 处,避 免 上 述 开 销,适 合 短 小 频 繁 调 用 的 函 数。

编 译 器 处 理 规 则

inline 是 建 议,非 强 制:编 译 器 可 能 忽 略 inline 声 明(如 函 数 体 复 杂、递 归 调 用 等)。
展 开 条 件:函 数 体 短 小,无 循 环、递 归 等 复 杂 结 构。
定 义 位 置:内 联 函 数 必 须 在 调 用 点 前 被 定 义(通 常 放 在 头 文 件 中),否 则 链 接 时 可 能 报 错,内 联 函 数 的 声 明 和 定 义 不 能 分 离。


auto 关 键 字

定 义

         auto 是 一 个 功 能 强 大 的 类 型 说 明 符,它 能 让 编 译 器 自 动 推 导 变 量 的 类 型,从 而 显 著 简 化 代 码。


基 本 语 法

         auto 的 基 本 语 法 是 在 声 明 变 量 时,用 auto 关 键 字 替 代 具 体 的 类 型,编 译 器 会 根 据 初 始 化 表 达 式 自 动 推 导 变 量 的 类 型。可 以 使 用 typeid 函 数 输 出 变 量 的 类 型。

#include<iostream>using namespace std;int main(){auto x = 42; //推导为intauto y = 3.14; //推导为doubleauto z = \"hello\"; //推导为const char*auto& ref = x; //推导为int&const auto& cref = x; //推导为const int&cout << typeid(cref).name() << endl;cout << typeid(ref).name() << endl;return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!


auto 在 数 组 中 的 应 用

#include<iostream>using namespace std;int main(){int arr[] = { 1, 2, 3, 4, 5 };for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){arr[i] *= 2;}//for (int* p = arr; p < arr + sizeof(arr) / sizeof(arr[0]); p++)//{//cout << *p << \" \";//}//cout << endl;//范围for//依次取数组中的数据赋值给e//自动迭代,自动判断结束//数组都可以for (auto e : arr){//e *= 2;cout << e << \" \";}cout << endl;for (auto& e : arr)//auto可以适用于任何数组,也可以使用int{e *= 2;}for (auto e : arr){cout << e << \" \";}return 0;}

关 键 点 总 结
引 用 是 修 改 的 关 键
         使 用 for(auto& e : arr)(带 引 用)可 直 接 修 改 原 数 组 元 素。
         使 用 for(auto e : arr)(值 拷 贝)只 能 读 取 数 据,修 改 无 效。

auto 的 优 势
         自 动 推 导 元 素 类 型,无 需 手 动 指 定。
         数 组 类 型 变 化 时 无 需 调 整,代 码 更 健 壮。

变 量 名 随 意
         e 可 替 换 为 任 意 合 法 标 识 符。


范 围 for 循 环 使 用 的 条 件

for 循 环 迭 代 的 范 围 必 须 是 确 定 的
         对 于 数 组 而 言,就 是 数 组 中 第 一 个 元 素 和 最 后 一 个 元 素 的 范 围;对 于 类 而 言,应 该 提 供 begin 和 end 的 方 法,begin 和 end 就 是 for 循 环 迭 代 的 范 围。

#include<iostream>using namespace std;void TestFor(int array[]){for (auto& e : array){cout << e << endl;}}int main(){int arr[] = { 1,2,3,4,5 };TestFor(arr);return 0;}

C++神级特性爆肝解析:函数重载 + 引用 + 内联函数 + auto+nullptr,吃透这些让面试官跪着求你入职!
         当 数 组 作 为 函 数 参 数 传 递 时,它 会 自 动 退 化 为 指 向 首 元 素 的 指 针。指 针 没 有 保 存 数 组 大 小 信 息(丢 失 了 sizeof(array)),范 围 for 需 要 知 道 数 组 的 起 始 和 结 束 位 置。


指 针 空 值(nullptr)

  1. 在 C++ 里,NULL 一 般 被 定 义 成 整 数 0,它 的 本 质 是 个 整 数 类 型。
  2. nullptr:这 是 C++11 新 引 入 的 关 键 字,它 的 类 型 是 std::nullptr_t。nullptr 能 够 隐 式 地 转 换 为 任 意 指 针 类 型,但 不 能 转 换 为 整 数 类 型。
  3. 在 使 用 nullptr 表 示 指 针 空 值 时, 不 需 要 包 含 头 文 件,因 为 nullptr 作 为 新 关 键 字 引 入 的。
  4. sizeof(nullptr) 与 sizeof((void*)0) 所 占 的 字 节 数 相 同。

在这里插入图片描述


总 结

         函 数 重 载、引 用、内 联 函 数、auto 和 nullptr 是 C++ 基 础 核 心。重 载 让 同 名 函 数 依 参 数 适 配 场 景;引 用 以 别 名 简 化 操 作、提 升 效 率;内 联 平 衡 调 用 开 销 与 复 用;auto 减 少 类 型 声 明 冗 余;nullptr 规 范 空 指 针。这 些 特 性 体 现 C++ 在 兼 容 与 创 新 间 的 平 衡,既 承 C 语 言 高 效,又 添 安 全 便 捷。吃 透 并 活 用 它 们,是 进 阶 高 阶 特 性 的 基 石,也 能 轻 松 应 对 面 试 基 础 考 点,助 你 扎 实 迈 入 C++ 之 门。