目录


前言

C++ 是一种通用的、高效的编程语言,由 Bjarne Stroustrup 于 1980 年代在贝尔实验室开发,最初作为 C 语言的扩展(最初称为“C with Classes”)。它结合了 低级内存操作(如 C 语言)和 高级抽象特性(如面向对象编程),广泛应用于系统开发、游戏引擎、嵌入式系统和高性能计算等领域。


一、c++简介

1.1 起源

C++ 的起源可以追溯到 20 世纪 80 年代初,由丹麦计算机科学家 Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)在 贝尔实验室(Bell Labs)开发。其设计初衷是结合 C 语言的高效性面向对象编程(OOP) 的特性,同时解决当时其他语言在系统编程中的局限性。

  1. C with Classes(1979–1983)

    • Stroustrup 最初将新语言称为 “C with Classes”,目的是在保留 C 语言底层控制能力的同时,引入 类(class)继承 和 多态 等面向对象特性。
    • 他受到 Simula(面向对象鼻祖)和 ALGOL 等语言的影响,但认为这些语言在性能和灵活性上无法满足系统编程需求。
  2. 正式命名为 C++(1983)

    • 1983 年,语言更名为 C++,名称中的 ++ 是 C 语言中的自增运算符,象征对 C 的改进和扩展。
    • 新增特性包括 虚函数运算符重载引用 和 常量(const 等。
  3. 首个商业版本(1985)

    • 1985 年,C++ 的第一个商业编译器 Cfront 发布,同时 Stroustrup 出版了经典著作《The C++ Programming Language》,成为语言的重要参考。
  4. 标准化进程(1998–至今)

    • 1998 年:首个国际标准 ISO/IEC 14882:1998(C++98)发布,确立了语言的核心规范。
    • C++11(2011):里程碑式更新,引入 自动类型推导(autoLambda 表达式右值引用 等现代特性。
    • 后续版本:C++14、C++17、C++20 持续增强功能,如 模块化(Modules)协程(Coroutines) 和 概念(Concepts)

1.2 c++的特点 

1. 多范式支持

  • 面向对象编程(OOP):支持类、封装、继承、多态(包括虚函数和抽象类)等特性。
  • 泛型编程:通过模板(Template)实现,支持类型无关的代码复用(如STL容器和算法)。
  • 过程化编程:保留C语言的特性,支持函数和模块化设计。

2. 高性能与底层控制

  • 直接内存操作:支持指针、手动内存管理,适合系统级开发。
  • 编译型语言:代码直接编译为机器码,运行效率接近底层硬件。
  • 资源敏感优化:支持内联汇编、寄存器变量等,适用于游戏引擎、高频交易等领域。

3. 标准模板库(STL)

  • 丰富的数据结构与算法:如vectormapsort等,提供高效实现。
  • 迭代器模式:统一访问容器元素的接口,增强代码通用性。
  • 函数对象与Lambda:支持函数式编程风格(C++11起)。

4. 内存管理

  • RAII(资源获取即初始化):通过对象生命周期自动管理资源(如文件句柄、内存),避免泄漏。
  • 智能指针:如unique_ptrshared_ptr(C++11引入),减少手动内存管理错误。

5. 现代语言特性(C++11及后续标准)

  • 自动类型推导auto关键字简化代码。

  • 移动语义与右值引用:避免不必要的拷贝,提升性能(如std::move)。

  • Lambda表达式:支持匿名函数,便于编写回调和高阶函数。

  • 并发支持std::thread、原子操作等标准库工具。

6. 灵活性与复杂性

  • 运算符重载:自定义类型支持运算符(如+<<),增强可读性。

  • 多重继承与虚基类:允许复杂对象关系,但需谨慎使用。

  • 模板元编程:编译时计算与类型推导,用于高性能库开发(如Boost)。

7. 兼容性与可移植性

  • 与C语言兼容:可直接调用C库,复用现有代码。

  • 跨平台支持:主流操作系统和硬件均有编译器(如GCC、Clang、MSVC)。

8. 静态类型系统

  • 编译时类型检查:提前发现类型错误,增强安全性。

  • 强类型约束:减少隐式类型转换的风险。

9. 异常处理

  • try/catch机制:支持错误处理,但部分场景推荐使用返回值或错误码。

10. 持续演进

  • 标准更新:每三年发布新标准(如C++20引入模块、概念约束),逐步简化语法并增强功能。


二、开发环境搭建 

建议使用CLion

但是为了解下来学习cQt做准备,所以这里介绍Qt的使用安装方法,但是qt写程序是真难用

Qt狗都不........用,用的就是Qt


2.1. 安装 Qt 开发工具

Windows 平台

  1. 下载 Qt 安装程序:

    • 访问 Qt 官网
    • 选择 "Download the Qt Online Installer"
  2. 运行安装程序:

    • 选择组件(至少选择 Qt 版本和 Qt Creator)
    • 推荐安装 MinGW 工具链(如果使用 MSVC 则需要安装 Visual Studio)
  3. 安装完成后,Qt Creator 将自动安装


2.2 修改编码环境 

修改默认编码


2.3创建第一个 Qt 项目

选择 "文件" > "新建文件或项目"

  1. 设置项目名称和路径
  2. 选择构建套件
  3. 完成向导后,点击 "运行" 按钮编译并执行程序

2.4 c++的编译过程

C++是一种典型的编译型语言,其代码执行需要经过完整的编译和链接过程。首先,程序员编写的源代码(.cpp/.h文件)会被编译器(如GCC、Clang或MSVC)进行词法分析、语法分析和语义检查,通过后生成与平台相关的目标文件(.o或.obj文件),该文件包含机器码和符号表但尚未解决外部依赖。接着,链接器将多个目标文件与库文件进行整合,解析函数和变量的引用关系,完成地址重定位,最终生成可执行文件(如Windows的.exe或Linux的.out)


2.5 代码示例 

// 引入输入输出流库,提供基本的输入输出功能
// iostream 包含标准输入输出对象如 cin, cout, cerr, clog 等
#include <iostream>

// 使用标准命名空间 std
// 这样可以直接使用 std 中的成员(如 cout, endl)而无需前缀 std::
using namespace std;

// 主函数,程序执行的入口点
// 每个C++程序必须有且仅有一个 main 函数
// int 表示该函数返回一个整数值
int main()
{
    // cout 是标准输出流对象,用于向控制台输出数据
    // << 是流插入运算符,用于将右侧的内容插入到左侧的流中
    // "Hello World!" 是要输出的字符串常量
    // endl 是特殊操作符,表示换行并刷新输出缓冲区
    // 这行代码会在控制台输出 "Hello World!" 并换行
    cout << "Hello World!" << endl;

    // return 语句结束 main 函数的执行
    // 返回 0 表示程序正常退出(非0值通常表示错误)
    // 在大多数操作系统中,0 表示成功,非0表示各种错误代码
    return 0;
}

2.6 qt疑难杂症 

2.6.1 遇到无法删除代码,一点击光标就变成小黑块

千万不要选这个!!!

取消勾选!!!


2.6.2 遇到运行不弹出终端 

改成启用

取消勾选! 


2.6.3 遇到终端有乱码

鎸?<RETURN> 鏉ュ叧闂獥鍙?..

在设置中修改语言设置 

 

修复成功!

让我们看看正常应该显示什么


三、词法符号

3.1 关键字

3.1.1 ANSI C 32个关键字

1. 存储类型

  • auto:自动变量(默认属性,通常省略)

  • extern:声明外部全局变量或函数

  • static:静态变量(作用域限制或持久化存储)

  • register:建议编译器将变量存储在寄存器中(现代编译器自动优化)

2. 数据类型

  • 基本类型charintfloatdouble

  • 修饰符

    • 长度:shortlong

    • 符号性:signedunsigned

  • 空类型void(用于函数返回值、指针、参数占位)

3. 控制语句

  • 条件分支ifelseswitchcasedefault

  • 循环控制forwhiledobreakcontinue

  • 跳转gotoreturn

4. 构造数据类型

  • struct:结构体(组合不同类型的数据)

  • union:共用体(共享内存空间的不同数据类型)

  • enum:枚举(定义命名常量集合)

5. 其他关键字

  • const:常量(值不可修改)

  • sizeof:计算变量或类型的内存大小

  • typedef:为类型定义别名

  • volatile:禁止编译器优化(用于硬件寄存器等场景)


3.1.2 C++ 补充的29个关键字

1. 数据类型增强

  • bool:布尔类型(值为 true/false

  • wchar_t:宽字符类型(Unicode支持)

2. 面向对象

  • class:定义类

  • private/protected/public:访问权限控制

  • friend:友元(允许非成员访问私有成员)

  • virtual:虚函数(实现多态)

  • this:指向当前对象的指针

3. 动态内存管理

  • new:动态分配内存

  • delete:释放动态内存

4. 模板与泛型编程

  • template:定义模板

  • typename:声明模板中的类型参数

5. 异常处理

  • try:异常检测代码块

  • catch:捕获并处理异常

  • throw:抛出异常

6. 运算符与函数特性

  • operator:运算符重载

  • inline:内联函数(减少函数调用开销)

7. 命名空间与别名

  • namespace:定义命名空间(避免命名冲突)

  • using:引入命名空间或定义类型别名

8. 其他

  • mutable:允许在const成员函数中修改成员变量

  • explicit:禁止隐式类型转换(构造函数)


3.2 标识符 

  1. 组成字符
    标识符只能由字母(A-Z, a-z)、数字(0-9)和下划线(_)组成,不允许其他特殊字符(如$@、空格等)。

  2. 首字符限制
    第一个字符必须是字母或下划线,不能是数字。

  3. 关键字冲突
    标识符不能与C语言的关键字(如intifreturn等)或保留标识符(如_Bool_Alignas等)相同。不同C标准(C89/C99/C11)的关键字可能不同,需注意兼容性。

  4. 区分大小写
    C语言严格区分大小写,例如varVarVAR是三个不同的标识符。

  5. 保留标识符

    • 双下划线(__)开头单下划线后跟大写字母(如_A的标识符保留给编译器或标准库使用(如__LINE___STDC__)。
    • 标准库函数名(如printfmalloc)和类型名(如size_tFILE)也应避免使用。

3.3 运算符 

3.3.1 算术运算符

运算符 名称 说明
+ 加法 数值相加或字符串拼接
- 减法 数值相减
* 乘法 数值相乘
/ 除法 整数除法截断小数(非向下取整),浮点数除法保留小数。如:5/2=2,5.0/2=2.5
% 取模 取余数(结果符号与被除数一致)。如:7%3=1,-7%3=-1
++ 自增 ++a(先自增后使用),a++(先使用后自增)
-- 自减 同自增逻辑

3.3.2 关系运算符

运算符 名称 说明
> 大于 比较数值大小
>= 大于等于
< 小于
<= 小于等于
== 等于 基本类型比较值,对象比较引用地址
!= 不等于

3.3.3 赋值运算符

运算符 名称 说明
= 赋值 右侧值赋给左侧变量
+= 加后赋值 a += 5等价于a = a + 5
-= 减后赋值
*= 乘后赋值
/= 除后赋值
%= 取模后赋值

3.3.4 逻辑运算符

运算符 名称 说明
&& 逻辑与 短路特性:左假则跳过右操作
|| 逻辑或
一真则真,全假为假
! 逻辑非 取反布尔值
& 非短路与 两侧均执行
| 非短路或 两侧均执行

3.3.5 位运算符

运算符 名称 说明
& 位与 两操作数位同为1时结果为1
| 位或 有1则1,全0则0
^ 按位异或 两操作数位不同时结果为1
~ 按位取反 单目运算符,0变1,1变0
<< 左移 高位丢弃,低位补0(等价乘2)
>> 带符号右移 正数补0,负数补1(等价除2,向下取整)
>>> 无符号右移 高位补0(负数会变正)

3.3.6运算符优先级(从高到低)

  1. ()[].
  2. ++--!~
  3. */%
  4. +-
  5. <<>>>>>
  6. >>=<<=
  7. ==!=
  8. &^|
  9. &&||
  10. ?:(三元运算符)
  11. =+=-=等赋值运算符

3.4 分隔符

空白字符包括:空格符( )、制表符(\t)、换行符(\n)。
它们在代码中的作用是 分隔语法单元,但不同语言对空白符的敏感度不同。

空白字符类型 作用场景 示例
空格符 分隔变量名、运算符、关键字等 int a = 5;
制表符 缩进代码块(Python强制要求) Python中:if x:\n\tprint(x)
换行符 表示语句结束或代码块分隔(如C/Java的分号) JavaScript中自动分号插入规则

3.5 标点符号 

1. 逗号 ,

  • 变量声明分隔int a = 1, b = 2;

  • 函数参数分隔void func(int x, float y);

  • 表达式分隔(逗号运算符):int c = (a++, b++);(按顺序执行)

  • 初始化列表std::vector<int> v = {1, 2, 3};

2. 分号 ;

  • 语句结束符int a;a = 10;

  • 控制结构结束if (cond) { ... };(注意:if 后的代码块不需要分号)

  • 类/结构体定义结束class MyClass {};(必须加分号)

  • do-while 循环结束do { ... } while (cond);

3. 冒号 :

  • 类继承class Derived : public Base {};

  • 成员初始化列表MyClass() : m_value(0) {}

  • 标签语句label: ... goto label;

  • 三目运算符condition ? a : b

  • 作用域限定符(C++11):enum class Color : int { Red, Green };

4. 花括号 {}

  • 代码块作用域if (cond) { ... }

  • 类/结构体/枚举定义struct Point { int x; int y; };

  • 初始化列表int arr[] = {1, 2, 3}; 或 std::vector<int> v{1, 2, 3};

  • Lambda 表达式(C++11):auto f = []() { ... };

5. 圆括号 ()

  • 函数调用/声明func();void func(int param);

  • 表达式优先级int c = (a + b) * 2;

  • 类型转换float f = (float)3.14;(C 风格)或 static_cast<float>(3.14);

  • 条件/循环结构if (cond) { ... }while (cond) { ... }

6. 中括号 []

  • 数组声明/访问int arr[5];arr[0] = 10;

  • Lambda 捕获列表(C++11):[&]() { ... }(捕获外部变量)

  • 下标运算符重载T& operator[](int index);

  • 属性说明符(C++11):[[nodiscard]] int func();


补充标点符号

7. 尖括号 <>

  • 模板参数std::vector<int> v;

  • 头文件包含#include <iostream>

8. 双冒号 ::

  • 作用域解析std::coutMyClass::staticMethod()

  • 全局命名空间::globalVar

9. 点 . 和箭头 ->

  • 成员访问obj.memberptr->member

10. 双引号 "" 和单引号 ''

  • 字符串字面量"Hello"

  • 字符字面量'A'

11. 反斜杠 \

  • 转义字符\n(换行)、\"(双引号)

12. 波浪号 ~

  • 析构函数~MyClass() {}

13. 问号 ?

  • 三目运算符condition ? true_expr : false_expr


四、变量 

4.1 格式

[存储类型] 数据类型 变量名;
  • 存储类型:决定变量的存储位置和生命周期(如 autostaticregisterextern
  • 数据类型:决定变量占用的内存大小和值域范围
  • 变量名:需符合标识符规则(字母/下划线开头,不含空格,区分大小写)

4.1.1 数据类型

类型名称 字节大小 值域范围 说明
char 1 -128 ~ 127 ASCII字符
unsigned char 1 0 ~ 255
short 2 -32,768 ~ 32,767
unsigned short 2 0 ~ 65,535
int 4 -231 ~ 231-1 默认整数类型
unsigned int 4 0 ~ 4,294,967,295
long 4/8 -231 ~ 231-1 或 -263 ~ 263-1 依赖系统架构
unsigned long 4/8 0 ~ 232-1 或 264-1
float 4 约6-7位有效数字 单精度浮点数
double 8 约15-16位有效数字 双精度浮点数
bool 1 false(0)/true(1) C++新增,需包含头文件
std::string 24-40* 动态字符串 C++类类型,需#include <string>

4.2 变量赋值

初始化方式

  1. 传统赋值
    int a = 100;
    char ch = 'A';  // 单引号表示字符
  2. 构造函数式
    float ft(3.14f);
  3. C++11统一初始化
    double dbl{3.1415926};  // 禁止窄化转换
    std::string s{"Hello"};

代码示例

#include <iostream>
using namespace std;
int main() {
    int a = 100;        // 整型变量,初始化为100
    char ch = 'q';      // 字符型变量,存储字符 'q'(ASCII码为113)
    float ft = 3.456;   // 单精度浮点型变量,初始化为3.456

    long st(2000);      // 长整型变量,使用直接初始化方式初始化为2000
    cout << ch << " " << st << endl; // 输出字符 ch 和长整型变量 st 的值,结果为 "q 2000"

    return 0;
}

4.3 局部变量与全局变量

特性 局部变量 全局变量
定义位置 函数或代码块内部 所有函数外部
存储区域 栈区(自动分配/释放) 全局区(程序启动到结束存在)
作用域 当前代码块 整个程序
生命周期 代码块执行期间 程序运行期间
默认值 未初始化时为随机值 自动初始化为零

4.4 内存分配

4.4.1 栈区(Stack)

  • 管理方式:编译器自动分配/释放(通过栈指针移动实现LIFO结构)
  • 存储内容
    • 局部变量(包括非静态局部变量、函数参数)
    • 函数调用上下文(返回地址、寄存器备份等)
  • 特性
    • 固定大小(Windows默认1-8MB,Linux默认8-10MB,可通过编译器选项调整)
    • 分配速度快(仅需移动栈指针)
    • 后进先出(LIFO)结构,函数返回时自动清理栈帧
  • 风险
    • 栈溢出(如深度递归、大型局部数组)

4.4.2 堆区(Heap / Free Store)

  • 管理方式:手动管理(new/deletemalloc/free
  • 存储内容:动态分配的对象(生命周期由程序员控制)
  • 特性
    • 空间大(受系统虚拟内存限制)
    • 分配速度慢(需搜索可用内存块,可能引发系统调用)
    • 易产生内存碎片和内存泄漏
  • 关键扩展
    • new vs mallocnew调用构造函数,malloc仅分配内存
    • 智能指针:自动管理堆内存(unique_ptrshared_ptr
    • 内存池:优化频繁分配场景(减少碎片,提升速度)

4.4.3 全局/静态区(Global/Static Area)

  • 存储内容
    • 全局变量
    • 静态变量(static修饰的局部/类成员变量)
    • 常量(根据类型和平台可能位于常量区)
  • 内存细分
    • .data段:已初始化的全局/静态变量
    • .bss段:未初始化的全局/静态变量(启动时清零)
  • 特性
    • 生命周期持续到程序结束
    • 线程安全问题需注意(多线程访问需同步)
  • 扩展
    • 线程局部存储thread_local关键字(C++11)

4.4.4常量区(Constant Area)

  • 存储内容
    • 字符串字面量(如"Hello"
    • 全局const变量(平台相关,可能合并到.rodata段)
  • 特性
    • 通常位于只读内存段(.rodata),修改会触发段错误
    • 生命周期与程序相同
  • 注意事项
    • 函数内const局部变量可能存储在栈区

4.4.5 代码区(Text Segment)

  • 存储内容:可执行代码(函数体、类方法)
  • 特性
    • 只读属性(防止意外修改指令)
    • 可能包含编译器优化的二进制指令

4.4.6 内存布局示意图

+------------------+
|     栈区         | ← 栈指针向下生长
+------------------+
|     堆区         | ← 动态向上生长
+------------------+
|   .bss 段        | (未初始化数据)
+------------------+
|   .data 段       | (已初始化数据)
+------------------+
|   .rodata 段     | (常量区)
+------------------+
|   Text 段        | (代码区)
+------------------+

五、常量

5.1 整型常量

  • 表示方式

    • 十进制:普通数字,如 123-45
    • 八进制:以 0 开头,如 0123(十进制83)。
    • 十六进制:以 0x 或 0X 开头,如 0x1A(十进制26)。
    • 二进制:以 0b 或 0B 开头(C++14起支持),如 0b1010(十进制10)。
  • 类型与后缀

    • 默认类型为 int,具体大小由编译器决定。
    • 后缀
      • u 或 U:无符号类型(如 123U 为 unsigned int)。
      • l 或 Llong 类型(如 123L)。
      • ll 或 LLlong long 类型(如 123LL)。
      • 可组合使用,如 0x1AULLunsigned long long)。

5.2 浮点常量

  • 表示方式

    • 小数形式:必须包含小数点或指数部分,如 3.140.5100.0
    • 科学计数法:用 e 或 E 表示指数,如 1.2e3(1200)、5E-2(0.05)。
  • 类型与后缀

    • 默认类型为 double
    • 后缀
      • f 或 Ffloat 类型,如 3.14f
      • l 或 Llong double 类型,如 3.14L

5.3 字符常量

  • 表示方式

    • 用单引号 '' 包裹,如 'A''5''#'
    • 转义字符:用于特殊符号,常见转义序列:
      • \n:换行,\t:制表符,\\:反斜杠。
      • \':单引号,\":双引号,\0:空字符。
  • 宽字符

    • 前缀 L 表示宽字符(wchar_t 类型),如 L'中'
  • 注意事项

    • 字符常量只能包含单个字符,多字符(如 'ab')可能导致编译器警告或未定义值。

5.4字符串常量

  • 表示方式

    • 用双引号 "" 包裹,如 "Hello""C++"
    • 隐式以 \0(空字符)结尾,例如 "a" 存储为 'a' 和 '\0'
  • 存储方式

    • C风格字符串const char[] 类型,如 const char* str = "Hello";
    • C++ string类std::string 类型,需包含 <string> 头文件。
  • 特性

    • 拼接:相邻字符串自动连接,如 "Hello" " World" 等价于 "Hello World"
    • 原始字符串(C++11):用 R"(...)" 避免转义,如 R"(Path: C:\Users\)"
  • 注意事项

    • 不可修改字符串字面量,如 char* s = "abc"; s[0] = 'x'; 会导致未定义行为。
    • 使用 char[] 初始化时可自动添加 \0,如 char arr[] = "abc";(长度为4)。
#include <iostream>  // 包含输入输出流库,用于使用cout和endl
using namespace std; // 使用标准命名空间,避免重复写std::

int main() // 主函数,程序入口
{
    // 用char类型存储单个字符,使用单引号包裹
    char st = 'a'; // 声明并初始化一个字符变量st,值为'a'

    // 字符串可以用字符数组或string类型存储
    // 字符数组:需预留空间存放结尾的'\0'空字符
    char arr[5] = "abc"; // 声明大小为5的字符数组,初始化为"abc"(实际占用4个元素:a,b,c,\0)
                         // 数组剩余位置自动填充为'\0'

    string str = "hello"; // 使用string类存储字符串,无需手动管理内存和大小

    cout << arr << endl; // 输出字符数组arr,遇到'\0'停止
    cout << str << endl; // 输出string字符串,自动处理内存和长度

    return 0; // 返回0表示程序正常退出
}

 六、输入输出

6.1 基础准备

#include <iostream>  // 必须包含的头文件
using namespace std; // 使用 std 命名空间(或显式写 std::cout)

6.2 输出语句 cout

  • 作用:向标准输出设备(如屏幕)发送数据。
  • 运算符<<(插入运算符),可连续拼接多个数据。
  • 换行控制:使用 endl 或 "\n"

示例代码

int age = 25;
cout << "Hello, World!" << endl;   // 输出字符串后换行
cout << "Age: " << age << "\n";   // 拼接变量和字符串,用 \n 换行

6.3 输入语句 cin

  • 作用:从标准输入设备(如键盘)读取数据。
  • 运算符>>(提取运算符),按顺序提取数据到变量。
  • 特性:自动跳过空白符(空格、制表符、换行)。

示例代码

int num;
double score;
cout << "Enter a number and a score: ";
cin >> num >> score;  // 连续输入多个值,用空格分隔

6.4 综合示例

// 包含标准输入输出流库
#include <iostream>

// 使用标准命名空间,避免重复写std::
using namespace std;

// 主函数,程序执行的入口点
int main()
{
    // 声明一个整型变量num,用于存储用户输入的值
    int num;

    // 输出提示信息,要求用户输入一个整数
    cout << "请输入一个整数:";
    
    // 从标准输入读取用户输入的值,并存储到num变量中
    cin >> num;
    
    // 输出用户输入的整数值,endl用于换行并刷新输出缓冲区
    cout << "num:" << num << endl;

    // 返回0表示程序正常结束
    return 0;
}

6.5 注意事项

  1. 命名空间:若未写 using namespace std;,需显式使用 std::cout 和 std::cin
  2. 数据类型匹配:输入时必须确保变量类型与数据一致,否则会导致错误状态。
    int x;
    cin >> x;  // 若用户输入非数字,x 将保留随机值,cin 进入错误状态
  3. 读取含空格的字符串cin >> name 遇到空格会停止,需用 getline 读取整行:
    string fullName;
    cout << "Enter full name: ";
    cin.ignore();                   // 清除之前输入残留的换行符
    getline(cin, fullName);         // 读取整行(包括空格)

6.6 输入输出流程图示

键盘输入 -> [cin] >> 变量       // 提取数据到变量
变量     -> [cout] << 屏幕显示  // 插入数据到输出流

掌握 cincout 是 C++ 交互的基础,后续可结合格式控制(如 <iomanip> 中的 setwsetprecision)进行更复杂的操作。


七、控制语句

7.1 分支语句 - if/else

基本语法

if (表达式) {
    语句块1;
} else {
    语句块2;
}

7.1.1 特性

  1. if-else关系

    • if可以单独存在,但else必须对应一个if
    • else必须紧跟最近的未匹配的if,中间不能插入其他代码。
  2. 代码块与作用域

    • 若省略大括号{}if/else仅控制紧随其后的一条语句。
      示例:
    if (num > 0)
        cout << "正数";  // 仅此句属于if
    else
        cout << "非正数"; // 仅此句属于else

7.1.2 完整示例:成绩分级

练习:从终端输入一个学生的成绩,判断学生成绩并打印成绩级别(使用if语句)
【90 - 100】 A
【80 - 89】 B
【70 - 79】 C
【60 - 69】 D
【小于60】 sorry you lost

#include <iostream>
using namespace std;
int main() {
    int score;
    cout << "请输入成绩(0-100): ";
    cin >> score;
    // 输入验证
    if (score < 0 || score > 100) {
        cout << "错误:成绩超出有效范围!" << endl;
        return 1;
    }
    // 分级判断
    if (score >= 90) {
        cout << "A" << endl;
    } else if (score >= 80) {
        cout << "B" << endl;
    } else if (score >= 70) {
        cout << "C" << endl;
    } else if (score >= 60) {
        cout << "D" << endl;
    } else {
        cout << "Sorry, you lost." << endl;
    }
    return 0;
}

7.2. 分支语句 - switch/case

7.2.1. 格式

switch(表达式) 
{
    case 常量1:
        语句块1;
        break;
    case 常量2:
        语句块2;
        break;
    // 更多 case...
    default:
        语句块n;
        break;
}

7.2.2. 特性

  1. 表达式类型限制

    • 表达式必须为 整型(如 intchar)或 枚举类型,不能为浮点类型(如 floatdouble)或字符串(如 char*、字符串字面量)。
  2. case 标签规则

    • case 后的常量必须是 整型常量表达式,且值唯一,不可重复。
    • 不允许使用变量或运行时计算的表达式。
  3. break 的作用

    • 每个 case 后通常需添加 break,否则程序会继续执行下一个 case 的语句块(称为 穿透效应)。
    • 利用穿透效应可合并多个 case 执行同一逻辑,但需明确注释以避免误解。
  4. default 分支

    • default 分支可选,用于处理未匹配的所有情况。
    • default 后的 break 可省略(若位于末尾),但若其后有其他 case,需谨慎处理穿透问题。
    • default 可置于任何位置,但通常放在末尾以提高可读性。
  5. 执行流程

    • 从匹配的 case 处开始执行,直至遇到 break 或 switch 结束。
    • 若无匹配 case 且存在 default,则执行 default 分支。

7.2.3 示例说明

int x = 2;
switch(x) {
    case 1:
        printf("One");
        break;
    case 2:
        printf("Two"); // 匹配后输出 "Two"
        // 无 break,继续穿透至 case 3
    case 3:
        printf("Three"); // 输出 "Three"
        break;
    default:
        printf("Unknown");
}
// 最终输出 "TwoThree"

7.3 循环语句for

7.3.1 基本语法结构

for(表达式1; 表达式2; 表达式3) {
    // 循环体
}
  • 表达式1:初始化语句(通常用于定义循环变量,仅在循环开始时执行一次)。
  • 表达式2:循环条件(布尔表达式,决定是否继续循环)。
  • 表达式3:更新语句(通常用于修改循环变量,在每次循环体执行后执行)。

7.3.2执行顺序

  1. 初始化:执行表达式1(为循环变量赋初值)。
  2. 条件检查:判断表达式2是否为 true
    • 若为 true,执行循环体。
    • 若为 false,退出循环。
  3. 更新循环变量:执行表达式3。
  4. 重复步骤2和3,直到条件为 false

7.3.3 示例代码分析 

#include <iostream>
using namespace std;

int main() {
    for(int i = 0; i < 5; i++) {
        cout << i << endl;
    }
    return 0;
}

输出

0
1
2
3
4

执行流程

  1. i 初始化为 0
  2. 检查 i < 50 < 5 为 true),执行循环体输出 0
  3. 执行 i++i 变为 1
  4. 重复条件检查,直到 i = 5 时条件不满足,循环终止。

7.3.4 关键特性

  1. 变量作用域

    • 循环变量可在表达式1中直接定义(如 for(int i = 0; ...)),此时 i 的作用域仅限于循环体内。
    • 若在外部定义(如 int i; for(i = 0; ...)),变量可在循环外访问。
  2. 灵活的表达式

    • 表达式1、表达式3可以为空或包含多个语句(用逗号分隔):
      for(int i = 0, j = 10; i < 5; i++, j--) {
          // 循环体
      }
      
  3. 无限循环

    for(;;) {
        // 需要内部通过 break 退出
    }
    

7.3.5 常见用法

  1. 遍历数组

    int arr[] = {1, 2, 3, 4, 5};
    for(int i = 0; i < 5; i++) {
        cout << arr[i] << " ";
    }
    // 输出:1 2 3 4 5
    
  2. 反向循环

    for(int i = 4; i >= 0; i--) {
        cout << i << " ";
    }
    // 输出:4 3 2 1 0
    
  3. 嵌套循环

    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            cout << "(" << i << "," << j << ") ";
        }
    }
    // 输出:(0,0) (0,1) (0,2) (1,0) ... (2,2)
    

7.3.6 练习:用for实现1-10求和

#include <iostream>
using namespace std;

int main() {
    int sum = 0; // 初始化累加器为0

    // for循环:i从1到10,每次递增1
    for (int i = 1; i <= 10; i++) {
        sum += i; // 将当前i的值累加到sum
    }

    cout << "1到10的和为:" << sum << endl; // 输出结果
    return 0;
}

前置递增 vs 后置递增

  • i++ 与 ++i 在循环中效果相同,但前置递增(++i)性能略优(对非内置类型更明显)。

7.4 循环语句-while

7.4.1基本语法

while (表达式) {
    // 语句块
}
  • 执行顺序:先判断表达式是否为 true,若为真则执行循环体,重复此过程直到表达式为 false
  • 特点:若初始条件为 false,循环体一次都不执行。

7.4.2 示例

int i = 0;
while (i < 10) {
    i++;
    if (i == 5) continue; // 跳过 i=5 的输出
    if (i == 8) break;    // 当 i=8 时终止循环
    cout << i << " ";
}
// 输出:1 2 3 4 6 7

 7.5 循环语句-do/while

 7.5.1语法结构

do {
    语句块;
} while (表达式);  // 注意:末尾必须有分号
执行顺序
  1. 先执行一次语句块,再判断表达式是否为真。
  2. 若表达式为 true,继续循环;若为 false,退出循环。

7.5.2 与 while 循环的关键区别

特性 while 循环 do/while 循环
执行顺序 先判断条件,再执行循环体 先执行循环体,再判断条件
最少执行次数 0 次(条件初始为 false 时) 1 次(无论条件是否满足)

7.5.3 示例代码分析

#include <iostream>
using namespace std;

int main() {
    int i = 0;

    // while 循环(被注释的原始代码)
    // while (i < 5) {
    //     cout << i << endl;
    //     i++;
    // }

    // do/while 循环
    do {
        cout << i << endl;
        i++;
    } while (i < 5);

    return 0;
}
输出结果

两种循环均输出:

0
1
2
3
4

原因

  • i 初始值为 0,满足 i < 5 的条件。
  • 两种循环均执行 5 次,直到 i 递增到 5 时退出。

7.6 练习题 

编写一个程序,该程序读取整数,直到输入0,输入终止后,程序报告输入的偶数(不包括0)的总个数,偶数的平均值,输入的奇数总个数和奇数的平均值。 

#include <iostream>  // 输入输出流库
#include <iomanip>   // 输入输出格式控制库

using namespace std;  // 使用标准命名空间

int main() {
    // 变量声明
    int num;                // 存储用户输入的临时变量
    int evenCount = 0;      // 偶数计数器
    int evenSum = 0;        // 偶数和
    int oddCount = 0;       // 奇数计数器
    int oddSum = 0;         // 奇数和

    // 用户输入提示
    cout << "Enter integers (0 to stop):\n";

    // 持续读取输入直到遇到0或非整数输入
    while (cin >> num && num != 0) {
        if (num % 2 == 0) {  // 判断是否为偶数
            evenCount++;     // 偶数计数增加
            evenSum += num;  // 累加偶数和
        } else {              // 奇数情况
            oddCount++;       // 奇数计数增加
            oddSum += num;    // 累加奇数和
        }
    }

    // 计算平均值(处理除零情况)
    // 使用 static_cast 确保浮点数除法
    double evenAvg = evenCount > 0 
        ? static_cast<double>(evenSum) / evenCount 
        : 0.0;
    double oddAvg = oddCount > 0 
        ? static_cast<double>(oddSum) / oddCount 
        : 0.0;

    // 设置固定小数点格式,保留两位小数
    cout << fixed << setprecision(2);
    
    // 输出统计结果
    cout << "Even numbers: " << evenCount 
         << ", average: " << evenAvg << endl;
    cout << "Odd numbers: " << oddCount 
         << ", average: " << oddAvg << endl;

    return 0;  // 程序正常退出
}

七、数组

8.1 定义

数组是具有相同数据类型内存连续的若干个变量的集合,组成数组的变量称为元素。


8.2 特点

  1. 数据类型相同
  2. 内存空间连续
  3. 支持随机访问(通过下标直接访问)

8.3 声明格式

[存储类型] 数据类型 数组名[元素个数];
  • 存储类型auto(默认)、staticextern
  • 元素个数:必须是常量表达式(C89标准)

8.4 初始化

  1. 全部初始化:可省略元素个数
    int arr[] = {1, 2, 3};  // 自动推断为 arr[3]
    
  2. 部分初始化:未初始化的元素自动补0
    int arr[5] = {1, 2};  // [1, 2, 0, 0, 0]
    
  3. 未初始化:元素值为随机值(静态数组自动初始化为0)

8.5 字符数组

初始化方式:
  1. 逐个字符初始化(需手动添加结尾符)
    char st[32] = {'a', 'b', 'c', '\0'};  // 显式添加结束符
  2. 字符串字面量初始化(自动补\0
    char st[32] = "hello";  // 实际占用6字节(含\0)
    char buf[] = "world";    // 自动推断为 buf[6]
    
关键区别:
  • char s[] = {'a','b','c'}; → 长度为3,无结束符
  • char s[] = "abc"; → 长度为4,包含\0

8.6 练习:斐波那契数列逆序输出 

#include <iostream>
using namespace std;

int main() {
    int arr[10] = {1, 1};  // 初始化前两项
    
    // 生成数列(从第3项开始)
    for (int i = 2; i < 10; i++) {
        arr[i] = arr[i-1] + arr[i-2];
    }
    
    // 逆序输出
    for (int i = 9; i >= 0; i--) {
        cout << arr[i] << " ";
    }
    return 0;
}

九、指针

9.1 概念

  • 地址:内存最小存储单元是字节,每个存储单元都有唯一编号(地址)
  • 指针变量:专门存储内存地址的变量(大小固定:32位系统4字节/64位系统8字节)
  • 指针本质:地址值的代称,指针变量是地址的容器

9.2 定义格式

[存储类型] 数据类型 *变量名; 
// 示例
int *p1;         // 指向int类型的指针
char *p2;        // 指向char类型的指针
double *p3 = nullptr; // 初始化为空指针

9.3 核心运算符

运算符 作用 示例
& 取变量地址 &num → 获取num的地址
* 解引用(访问地址内容) *p → 获取指针指向的值

9.4 指针运算

9.4.1 赋值运算

#include <iostream>
using namespace std;

int main()
{
    int num = 10;  // 定义一个整型变量num并初始化为10
    
    // 1.定义指针变量,将num变量的地址赋值给指针
    int *ptr = &num;  // &为取地址操作符,获取num的内存地址
                      // *在声明中表示ptr是一个int型指针变量
    // 验证指针存储的地址和变量的地址一致
    cout << &num << endl;  // 直接输出num的十六进制地址
    cout << ptr << endl;   // 输出指针变量ptr存储的地址值(应与上一行相同)
    
    // 通过指针访问内存数据(解引用)
    cout << *ptr << endl;  // *在表达式中表示解引用,获取指针指向地址的内容(即num的值10)

    int arr[5] = {1, 2, 3, 4, 5};  // 定义一个包含5个元素的整型数组
    
    // 2.定义一个指针,指向数组的首地址
    int *qtr = arr;  // 数组名arr默认表示数组首元素地址
                     // 等效于 int *qtr = &arr[0];
    cout << *qtr << endl;        // 输出数组第一个元素值1
    
    // 指针算术运算:访问数组后续元素
    cout << *(qtr+1) << endl;    // +1按元素单位移动(地址实际增加sizeof(int)字节)
                                 // 访问数组第二个元素值2(等价于qtr[1])

    // 3.将一个指针赋值给另一个指针
    qtr = ptr;       // 指针赋值使qtr也指向num的地址
                    // 此时qtr与ptr同为指向num的指针,*qtr等价于*ptr和num
                    
    return 0;
}

9.4.2 算术运算

  • 特点:以数据类型大小为步长
int arr[5] = {10,20,30,40,50};
int *p = arr;
p++;       // 移动sizeof(int)字节 → 指向arr[1]
p += 2;    // 指向arr[3]
int diff = p - arr; // 结果3(间隔元素个数)

9.4.3 关系运算
  • 规则:比较内存地址高低(需指向同一连续内存区域)
int *p1 = &arr[0];
int *p2 = &arr[2];
cout << (p1 < p2);  // 输出1(true)

9.5 练习

练习:使用指针实现将字符串转换成整数。

如:"234" -->234

#include <iostream>
using namespace std;

/**
 * 将字符串转换为整数的函数
 * @param str 指向数字字符串的指针,字符串应仅包含数字字符('0'~'9')
 * @return 转换后的整数值
 * @note 该函数假设输入字符串格式正确,不处理符号、空格或无效字符
 */
int string_to_int(const char* str) {
    int result = 0;            // 初始化结果为0
    
    // 遍历字符串中的每个字符,直到遇到空终止符'\0'
    while (*str != '\0') {
        // 将当前字符转换为对应数字:ASCII值相减(例如'5' - '0' = 5)
        // 将已有结果左移一位(乘以10),然后加上新的个位数
        result = result * 10 + (*str - '0');
        
        str++;                 // 指针移动到字符串的下一个字符
    }
    return result;
}

int main() {
    const char* str = "234";   // 待转换的数字字符串
    int num = string_to_int(str);
    cout << num << endl;       // 输出转换结果:234
    return 0;
}

总结

        C++作为Bjarne Stroustrup在1980年代开发的通用高效编程语言,融合了C语言的底层控制能力和面向对象、泛型编程等高级特性,成为系统开发、游戏引擎和高性能计算领域的核心工具。其演进历程从“C with Classes”到C++11/20的现代化改进,持续引入自动类型推导、智能指针、协程等特性,平衡性能与开发效率。文章系统解析了C++的起源、多范式支持、内存管理机制、开发环境搭建(如Qt工具链)、语法结构(词法符号、控制语句)、数据存储(变量、数组、指针)及输入输出操作,同时探讨了其灵活性与复杂性的双重特征,为开发者提供了从基础到实践的全面指南。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐