跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 基础概念详解

梳理了 C++ 核心基础机制,涵盖命名空间解决标识符冲突的原理与用法,标准输入输出流的操作规范,缺省参数的声明限制与调用逻辑,函数重载的判定条件及实现细节。重点解析了引用作为变量别名的内存操作优势,区分了普通引用与 const 引用对临时变量及权限的控制差异,对比了指针与引用的特性。此外还探讨了宏与内联函数的区别,以及 nullptr 关键字在消除空指针歧义中的必要性。

城市逃兵发布于 2026/3/26更新于 2026/9/1246 浏览
C++ 基础概念详解

C++ 基础概念详解

C++ 设计之初就保持了与 C 语言的兼容性,因此我们完全可以在 C++ 环境下编写 C 代码。

C++ 之父:本贾尼・斯特劳斯特卢普。

一、命名空间

在 C++ 中,标识符(变量、函数、类、常量、命名空间)的查找遵循特定规则。简单来说,编译器会从当前最内层的作用域开始查找;一旦找到,就不会再去外层作用域查找。

这就引出了一个问题:如果同一作用域下存在同名的标识符怎么办?

1. 命名冲突的本质

#include <stdio.h>
#include <stdlib.h>

int main() {
    int rand = 10;
    printf("%d\n", rand); // 代码可以正确执行
}

上面的代码能跑通,因为局部变量 rand 屏蔽了全局的 rand 函数。但如果把 rand 定义成全局变量呢?

#include <stdio.h>
#include <stdlib.h>

int rand = 10; // 全局变量

int main() {
    printf("%d\n", rand); // 会编译报错
}

这是因为 stdlib.h 中也声明了 rand 函数,导致全局作用域下出现同名标识符冲突。

2. 命名空间的概念

为了解决这个问题,C++ 引入了命名空间。你可以把它理解为自己造的一个域,用来存放标识符,避免污染全局环境。

语法:

namespace 命名空间名 {
    // 你自定义的标识符
}

使用方式:

通过 命名空间名::标识符 来访问域里的内容。

#include <stdio.h>
#include <stdlib.h>

namespace mycode {
    int rand = 10;
}

int main() {
    printf("%d\n", mycode::rand); // 正常打印出 10
}

3. 命名空间的嵌套

如果在同一个命名空间下还有冲突,可以使用嵌套命名空间。这就像在父域里开辟多个子域。

#include <stdio.h>

namespace code {
    namespace codeA {
        int a = 10;
    }
    namespace codeB {
        int a = 20;
    }
}

int main() {
    printf("%d\n", code::codeA::a); // 打印 10
    printf("%d\n", code::codeB::a); // 打印 20
}

4. 命名空间的使用技巧

除了显式指定,我们还可以展开成员或整个命名空间。

  • 展开某个成员:
    using name::a;
    
  • 展开命名空间的全部成员:
    using namespace name;
    

注意: 在多个文件中使用命名空间时,C++ 允许同一个命名空间被写在不同的文件、不同的位置,编译器会自动把它们合并成一个。这也是为什么 C++ 标准库都存放在 std (standard) 这个命名空间中。

二、C++ 的输入输出

1. iostream 头文件

<iostream> 是 Input Output Stream 的缩写,提供了 cin、cout 以及操作符 <<、>>。

2. cin 和 cout

std::cin 代表控制台输入,std::cout 代表控制台输出。由于它们都在 std 命名空间下,使用前通常加上 std:: 前缀,或者引入 using namespace std;。

  • cin:Console Input
  • cout:Console Output

3. 流运算符

  • <<:流插入运算符,配合 cout 使用。可以一次打印多个内容。
  • >>:流提取运算符,配合 cin 使用。也可以一次读取多个内容。
#include <iostream>
using namespace std;

int main() {
    cout << "hello world" << endl;
    cout << "第一行内容" << endl << "第二行内容" << endl;
}
#include <iostream>
using namespace std;

int main() {
    int a, b;
    cout << "请输入两个整数:";
    cin >> a >> b;
    cout << "两个数之和为:" << a + b << endl;
}

这里有个便利之处:C++ 可以自动识别变量类型,不需要像 C 语言那样手动指定占位符。

  • endl:表示换行并刷新缓冲区。

三、缺省参数

1. 基本概念

定义函数时,给参数一个默认值。调用时如果不传参,就用默认值;如果传了,就用实参。

#include <iostream>
using namespace std;

void Print(int a = 3) {
    cout << a << endl;
}

int main() {
    Print();      // 打印 3
    Print(6);     // 打印 6
}

2. 全缺省与半缺省

  • 全缺省: 所有参数都有默认值。
  • 半缺省: 部分参数有默认值。关键点: 缺省值必须从右向左连续设置。调用时必须传够没有缺省值的参数,且顺序是从左向右。
#include <iostream>
using namespace std;

// 错误示例:Print(); 没有传够参数,会触发编译错误
// 正确:Print(0); 打印 0,1,2
void Print(int a, int b = 1, int c = 2) {
    cout << a << "," << b << "," << c << endl;
}

函数声明与定义分离时的注意事项: 缺省参数只能出现一次,且必须出现在声明部分。

#include <iostream>
using namespace std;

void Print(int a, int b = 3); // 声明部分,缺省值写在这里
void Print(int a, int b) {    // 定义部分
    cout << a << "," << b << endl;
}

int main() {
    Print(3); // 打印 3,3
    Print(2, 6); // 打印 2,6
}

四、函数重载

C++ 允许在同一作用域内存在多个同名函数,但必须满足以下条件之一:

  1. 参数个数不同
  2. 参数类型不同
  3. 参数顺序不同
#include <iostream>
using namespace std;

// 参数个数不同
int Add(int a, int b, int c) {
    return a + b + c;
}

int Add(int a, int b) {
    return a + b;
}

int main() {
    int a = Add(1, 1, 1);
    int b = Add(1, 1);
    cout << a << endl << b << endl;
}
#include <iostream>
using namespace std;

// 参数类型不同
int Add(int x, int y) {
    return x + y;
}

double Add(double x, double y) {
    return x + y;
}

int main() {
    int a = Add(2, 3);
    double b = Add(1.2, 1.3);
    cout << a << endl << b << endl;
}
#include <iostream>
using namespace std;

// 参数顺序不同
double Calc(int a, double b) {
    return a + b;
}

double Calc(double a, int b) {
    return a - b;
}

int main() {
    double a = Calc(2, 2.2);   // 匹配第一个重载,结果 4.2
    double b = Calc(2.2, 2);   // 匹配第二个重载,结果 0.2
    cout << a << endl;
    cout << b << endl;
}

五、引用(Reference)

1. 基本概念

引用是给已有的变量起一个别名,直接在原内存上操作,不产生新的副本。

语法:

类型& 引用别名 = 引用对象;

2. Swap 函数的对比

用指针交换需要解引用,比较繁琐;用引用则更直观。

指针写法:

#include <iostream>
using namespace std;

void Swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main() {
    int a = 2, b = 3;
    cout << "交换前 a = " << a << " b = " << b << endl;
    Swap(&a, &b);
    cout << "交换后 a = " << a << " b = " << b << endl;
}

引用写法:

#include <iostream>
using namespace std;

void Swap(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int a = 2, b = 3;
    cout << "交换前 a = " << a << " b = " << b << endl;
    Swap(a, b);
    cout << "交换后 a = " << a << " b = " << b << endl;
}

3. 引用的要求

  • 初始化: 局部或全局引用必须初始化。函数形参的引用在传入实参时即完成初始化。
  • 命名: 不同作用域下引用别名可相同,但同一作用域下不能与原变量名相同。
  • 多引用: 一个变量可以有多个引用,修改其中一个,其他引用指向的值也会变。
  • 绑定问题: 引用一旦绑定某个实体,就不能再改变绑定对象(虽然可以赋值修改其值)。
#include <iostream>
using namespace std;

int main() {
    int a = 2;
    int& b = a;
    int& c = a; // 也可以写成 b
    cout << "变化前 a = " << a << ", b = " << b << ", c = " << c << endl;
    c++; // 修改 c
    cout << "变化后 a = " << a << ", b = " << b << ", c = " << c << endl;
}

4. 引用的优点

引用常用于函数传参或返回值,因为它直接操作内存,避免了拷贝开销,提高了效率。

六、const 引用

1. 概念

被 const 修饰的引用。权限只能不变或变小,不能放大。

  • 原变量只读 -> const 引用仍只读。
  • 原变量可读可写 -> const 引用变为只读。
int main() {
    int a = 3; // 可读可写
    const int& ra = a; // 只读
    a = 6; // 正确,未超出原变量权限
    // ra = 3; // 错误,超出了 const 引用权限
}

2. 修饰临时变量

普通引用不能绑定临时变量(如字面量、表达式结果),因为临时变量生命周期短且不安全。但 const 引用 可以延长临时变量的生命周期,直到引用销毁。

int main() {
    const int& ra = 20; // 安全
    // int& rra = 20; // 不安全,属于权限放大
    
    int a = 20;
    const int& ra2 = a * 3; // 安全
    // int& rra2 = a * 3; // 不安全
}

3. 引用与指针的区别

特性引用指针
语法别名,不开新空间存储地址,需开空间
初始化必须初始化建议初始化
绑定后不可更改可重新绑定
访问直接访问需解引用
大小取决于对象取决于系统位数
安全性无空指针/野指针可能出现空/野指针

七、宏

1. 概念

宏是在预处理阶段进行的文本替换,分为有参和无参宏。

2. 无参宏

#define val 18
int main() {
    cout << val << endl; // 编译器会将 val 替换为 18
}

3. 有参宏

#define Add(a,b) ((a) + (b))
int main() {
    cout << Add(2, 3) << endl; // 输出 5
}

注意括号的使用是为了避免运算符优先级带来的计算错误。

八、inline 内联函数

1. 概念

被 inline 修饰的函数,编译器会在调用处展开代码,无需建立栈帧,从而提高效率。

2. 注意

inline 只是建议,编译器有权决定是否采纳。通常用于几行的小代码。

#include <iostream>
using namespace std;

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

int main() {
    cout << Add(2, 3) << endl; // 相当于 cout << 2+3 << endl;
}

3. 内联函数 vs 宏

  • 本质: 内联是函数,宏是文本替换。
  • 调试: 内联函数可调试,宏不可。
  • 类型检查: 内联函数有类型检查,宏没有。
  • 优先级: 内联函数不受影响,宏需注意括号。

九、nullptr

1. 概念

nullptr 是 C++11 引入的关键字,专门用来表示空指针。

2. 引入原因

在 C++ 中,NULL 通常定义为 0。在函数重载时,0 既可以匹配整型参数,也可以匹配指针参数,导致歧义。

#include <iostream>
using namespace std;

void Print(int* x) {
    cout << "int*" << endl;
}

void Print(int x) {
    cout << "int" << endl;
}

int main() {
    Print(NULL);   // 可能调用 Print(int),因为 NULL 是 0
    Print(nullptr); // 明确调用 Print(int*),符合预期
}

使用 nullptr 可以避免这种二义性,让代码意图更清晰。

目录

  1. C++ 基础概念详解
  2. 一、命名空间
  3. 1. 命名冲突的本质
  4. 2. 命名空间的概念
  5. 3. 命名空间的嵌套
  6. 4. 命名空间的使用技巧
  7. 二、C++ 的输入输出
  8. 1. iostream 头文件
  9. 2. cin 和 cout
  10. 3. 流运算符
  11. 三、缺省参数
  12. 1. 基本概念
  13. 2. 全缺省与半缺省
  14. 四、函数重载
  15. 五、引用(Reference)
  16. 1. 基本概念
  17. 2. Swap 函数的对比
  18. 3. 引用的要求
  19. 4. 引用的优点
  20. 六、const 引用
  21. 1. 概念
  22. 2. 修饰临时变量
  23. 3. 引用与指针的区别
  24. 七、宏
  25. 1. 概念
  26. 2. 无参宏
  27. 3. 有参宏
  28. 八、inline 内联函数
  29. 1. 概念
  30. 2. 注意
  31. 3. 内联函数 vs 宏
  32. 九、nullptr
  33. 1. 概念
  34. 2. 引入原因

更多推荐文章

查看全部
  • Python 调用 Doubao-Seedream-4.5 生成图像接口示例
  • Python 面向对象编程实战:构建智能家居系统
  • C++逆向工程:用c++filt解析GCC编译后的函数名
  • Python 3.12 logging 模块:NullHandler 详解
  • 全国计算机等级考试三级证书报考指南与科目解析
  • 以太坊关键漏洞被发现,开发者获赏 1272 万元
  • 新能源汽车实训系统:数字孪生与 VR/AR 技术架构
  • Scapy 详细安装教程、功能介绍与快速上手
  • LLaMA Factory 核心原理讲解
  • 前端面试核心知识点整理(含 JavaScript、Vue、React 等)
  • Java 多用户网页版聊天室:项目总览与用户及好友管理模块实现
  • Vue 社区新动态:AI Elements Vue 获尤雨溪关注,填补 AI UI 空白
  • C++ 并发模型:内存序、可见性与指令重排
  • Less 预处理器实战:三种运行模式与核心语法解析
  • ToDesk 内置 ToClaw AI:零代码实现科技新闻日报自动化实战
  • 为什么 Python 代码在函数中运行得更快
  • OFDM 调制解调系统的 FPGA 实现:从仿真到硬件
  • UI UX Pro Max:让 AI 辅助生成专业级前端 UI
  • 鸿蒙 Flutter 智能家居应用开发实战指南
  • SkyWalking 多语言探针现状:.NET、C++ 与 Lua 实践指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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