1. C++发展简史与版本特性

C++由Bjarne Stroustrup于1979年在贝尔实验室开始设计,1983年正式命名为C++。它在C语言的基础上增加了面向对象编程的特性(类、封装、继承等)。随后经历了C++98(第一个标准化版本)、C++03(修订)、C++11(革命性更新)、C++14/17/20/23等版本。

💡 小故事:原本计划C++23加入网络库(networking),但因标准委员会内部对sender/receiver模型的争议而推迟到C++26。C++标准的演进往往需要多年打磨,这也保证了它的稳定性。

2. 命名空间(namespace)

为什么需要命名空间?

在C语言中,全局作用域下很容易发生命名冲突。例如:

C++使用namespace将标识符隔离到不同的域中,从而解决名字污染问题。

定义与使用

命名空间可以嵌套、可以跨文件合并

(同一个namespace出现在多个文件中会自动合并)。

例如

3. C++输入输出 —— cin/cout

C++使用iostream库提供的cincout进行输入输出,自动识别类型,不再需要printf/scanf的格式化字符串。

例如

  • << 是流插入运算符,>> 是流提取运算符。

  • endl 相当于换行 + 刷新缓冲区。

  • 日常练习可以用using namespace

    4. 缺省参数(默认参数)

    缺省参数是指在函数声明或定义时为形参指定一个默认值。

  • 调用时如果不传参,就使用默认值。

  • 分类

  • 全缺省:所有参数都有默认值

  • 半缺省:只有部分参数有默认值(必须从右往左连续缺省,注意是有顺序的!

  • std,但大型项目不建议(避免标准库命名污染)⚠️ 注意:缺省参数不

    5. 函数重载(Overload)

    C++允许同一作用域中出现同名函数,只要它们的参数列表不同(个数、类型或顺序)。返回值不同不能作为重载条件。(通过参数列表的不同来区分它们)

    能在声明和定义中同时出现。一般放在声明中,定义中不再写默认值。

    调用时,编译器根据实参的类型和数量自动匹配对应的函数。

  • 下面两个函数不能构成重载(调用会歧义):

  • 选项 1: 调用 void f1() —— 完美匹配,因为参数数量 0 对 0。

  • 选项 2: 调用 void f1(int a = 10) —— 因为参数有默认值 10,它在缺省参数的情况下也能匹配 0 个参数的调用。

6. 引用(Reference)

引用是已存在变量的别名,不占用额外内存,与引用的对象共用同一块空间。

基本用法

引用特性

  1. 定义时必须初始化

  2. 一个变量可以有多个引用

  3. 引用一旦绑定,不能再改变指向(这一点和指针不同)

引用的使用场景

  • 引用传参(替代指针,更简洁)

  • 引用返回值(可修改返回值)

  • const 引用

  • 可以引用 const 对象(权限不能放大)

  • “权限放大” 是 C++ 中一个非常重要的安全机制。简单直接的结论是:

    不能把一个“只读”的变量(const),交给一个“可写”的别名(普通引用 &)。

  • 可以引用临时对象(表达式结果、类型转换产生的临时变量) 

  • 代码运行

  • 指针 vs 引用

  • 7. inline内联函数

    C++的inline关键字用于建议编译器将函数调用替换为函数体代码,从而避免函数调用建立栈帧的开销,特别适合短小频繁调用的函数。

    为什么需要 inline?

    C语言中常用宏函数(#define)来避免函数调用,但宏有很多缺陷:

  • 缺少类型检查

  • 容易写错(括号问题)

  • 无法调试

  • ⚠️ inline只是建议,编译器可能忽略(比如递归、函数体过大),因此inline不一定会展开
    ⚠️ inline函数不要声明和定义分离(否则链接错误),应直接定义在头文件中。

  • 8. nullptr —— 更安全的空指针

    在C++98中,NULL通常被定义为0,这会导致重载函数调用的二义性。

  • nullptr 是C++11引入的关键字,它可以隐式转换为任何指针类型,但不能转换为整数类型,因此能够精确匹配指针版本的重载函数。

  • 9. 核心总结

  • 如果觉得有用,欢迎点赞、收藏、评论交流~

更多推荐