Skip to content

C++编程语言 01:从 Python 到 C++ 的启航

引言:欢迎来到 C++ 的世界!

各位同学,大家好!很高兴能和大家一起开启 C++ 的学习之旅。相信大家已经掌握了 Python 编程的基础,对编程的思想和逻辑有了初步的认识。那么,为什么要学习 C++ 呢?C++ 又会给我们带来什么新的体验和挑战呢?这就是我们今天课程要探讨的内容。

一、 C++ 与 Python 的对比:理解差异,扬长避短

我们首先来对比一下 C++ 和大家熟悉的 Python,了解它们的优势和适用场景,从而更好地理解学习 C++ 的意义。

速度和效率:

  • C++: 编译型语言,执行速度快,效率高。 C++ 代码在运行前会被完整地编译成机器可以直接执行的二进制代码,这使得 C++ 在执行效率上具有天然的优势,尤其是在处理大量计算和对性能有极致要求的场景下。
  • Python: 解释型语言,执行速度相对较慢,但开发效率高。 Python 代码在运行时逐行解释执行,这牺牲了一部分执行效率,但换来了更快的开发速度和更简洁的语法,非常适合快速原型开发和脚本编写。

内存管理:

  • C++: 需要手动管理内存。 C++ 允许程序员直接控制内存的分配和释放,这赋予了开发者更高的灵活性和优化空间,但也带来了内存泄漏等风险。
  • Python: 自动内存管理(垃圾回收机制)。 Python 自动处理内存分配和回收,降低了开发者的心智负担,但也可能在某些情况下带来性能上的开销。

应用领域:

  • C++: 性能敏感型应用、系统级编程、游戏开发、嵌入式系统、高性能计算等。 由于其高效的执行速度和对硬件的直接控制能力,C++ 在这些领域扮演着重要的角色。
  • Python: 数据分析、人工智能、Web 开发、自动化脚本、快速原型开发等。 Python 的简洁语法和丰富的库使其在这些领域非常受欢迎。

为什么人工智能班级学习 C++?

  • 深入理解底层原理,为算法优化提供基础。 AI 的核心算法往往涉及大量的计算,了解 C++ 可以帮助我们理解这些算法在底层是如何高效执行的,从而为算法优化提供思路。
  • 部分高性能库和框架使用 C++ 开发,学习 C++ 有助于更好地使用和理解这些工具。 许多流行的深度学习框架(如 TensorFlow、PyTorch 的底层)都是用 C++ 实现的,掌握 C++ 可以更深入地了解它们的运行机制,甚至进行二次开发。
  • 提升编程技能和代码效率。 C++ 的学习能够锻炼我们对内存管理、性能优化等方面的理解,提升我们的编程基本功,并编写出更高效的代码。

二、 C++ 的发展与平台:历史的脉络与选择

了解 C++ 的发展历程和它所运行的平台,有助于我们更好地理解这门语言的特点和应用场景。

  • C++ 的发展历程:从机器到现代

    • 机器语言: 计算机最早只能理解的语言,用二进制代码表示指令,例如 0001101000非常难以理解和编写。
    • 汇编语言: 用助记符代替二进制代码,例如 mov, jmp, add相较于机器语言更容易理解,但仍然很底层,开发效率不高。
    • 高级语言 (C语言): 更接近人类语言,更容易理解和编写,例如 int x = 5;提高了开发效率,但仍然偏向过程式编程。
    • C++: 在C语言基础上发展而来, 由 Bjarne Stroustrup 于 1979 年在贝尔实验室开发。增加了面向对象特性(类、继承、多态),并持续引入泛型编程、Lambda 表达式等现代特性,兼顾开发效率和执行效率。 C++ 可以看作是 C 语言的增强版,它既保留了 C 的高效性,又加入了许多现代编程的特性。
  • C++版本:不断进化的语言

    • C++98/03: C++ 的早期稳定版本。
    • C++11: 一个重要的里程碑版本,引入了大量现代特性,如智能指针、Lambda 表达式、自动类型推断等,是学习现代 C++ 的基础。
    • C++14, C++17, C++20...: 后续版本不断引入新特性和改进,使 C++ 更加强大和易用。我们建议学习最新的稳定版本,目前 C++20 或更新版本是主流。

三、 C++ 编译原理:从代码到执行

与 Python 的解释执行不同,C++ 是一门编译型语言。理解编译过程对于学习 C++ 至关重要。

Python:解释型语言,逐行解释执行代码。 就像我们阅读文章一样,Python 解释器会一行一行地理解并执行代码。

C++:编译型语言,需要先将代码编译成机器语言才能执行。 C++ 代码需要经过一个“翻译”的过程,将其转化为计算机能够理解的机器语言。

编译过程详解:

  1. 预处理 (Preprocessing):

    • 处理以 # 开头的预处理指令。
    • 例如:
      • #include <iostream>:将 iostream 头文件的内容复制到当前文件中。
      • #define PI 3.14159:将代码中的 PI 替换为 3.14159
    • 预处理的输出结果是一个包含了所有必要代码的源文件。
  2. 编译 (Compilation):

    • 将预处理后的 C++ 代码翻译成汇编语言
    • 汇编语言是一种更接近机器语言的低级语言,使用助记符表示机器指令。
  3. 汇编 (Assembly):

    • 将汇编语言代码翻译成机器语言(也称为目标代码)。
    • 机器语言是由二进制指令组成的,计算机可以直接执行。
    • 汇编器的输出结果是一个或多个目标文件 (.obj.o 文件)。
  4. 链接 (Linking):

    • 将多个目标文件和所需的库文件(包含已经编译好的函数和代码)合并成一个最终的可执行文件 (.exe 或无后缀文件)。
    • 链接器负责解决符号引用问题,例如将函数调用与函数定义连接起来。

四、 C++ 开发环境搭建:工欲善其事,必先利其器

选择合适的开发环境能大大提高我们的学习和开发效率。

推荐使用 CLion:

  • 跨平台开发工具,支持 Windows、Linux、macOS 等平台。 无论你使用哪种操作系统,CLion 都能提供一致的开发体验。
  • 专为 C++ 设计的集成开发环境 (IDE),提供代码补全、语法高亮、调试、重构等强大功能。 这些功能可以帮助我们更快更准确地编写代码,并更容易发现和修复错误。
  • 与 CMake 构建系统无缝集成,方便项目管理。 CMake 是一个流行的跨平台构建工具,CLion 的集成使得管理复杂的 C++ 项目变得更加容易。

CLion 安装演示:

  1. 下载 CLion 安装包:

  2. 运行安装程序,根据提示完成安装。

  3. 启动 CLion,配置 C++ 工具链。

    • CLion 需要一个 C++ 编译器才能工作。常见的编译器有 GCC、Clang 和 Visual Studio 的 MSVC。
    • 在首次启动 CLion 时,它会提示你选择或配置编译器。
    • 在 Windows 上,通常会选择 MinGW 或安装 Visual Studio Community,并配置其编译器。
    • 在 Linux 和 macOS 上,通常系统已经自带 GCC 或 Clang。

TIP

其他开发环境:

  • GCC/G++: 开源编译器,使用命令行操作,适合有一定基础的开发者,可以更深入地了解编译过程。
  • Visual Studio: 微软开发的集成开发环境,功能强大,尤其在 Windows 平台开发中表现优秀,但体积较大。
  • VS Code with C/C++ Extension: 轻量级但功能强大的代码编辑器,通过安装 C/C++ 扩展可以获得代码补全、调试等功能,适合喜欢自定义配置的开发者。

五、 第一个 C++ 程序:迈出 C++ 编程的第一步

让我们一起编写并运行你的第一个 C++ 程序!

c++
#include <iostream> // 引入 iostream 头文件,提供输入输出功能

using namespace std; // 使用标准命名空间,简化代码

int main() { // 主函数,程序执行的入口
  cout << "Hello, world!" << endl; // 使用 cout 输出字符串到控制台,并换行
  return 0; // 返回值 0 表示程序正常结束
}

好的,我将你提供的 C++ 基础数据类型部分进行补充和完善,使其成为更完整的第一节课后半部分内容。

六、C++ 数据类型

我们已经了解了 C++ 的一些基本特性,现在让我们深入了解 C++ 中的数据类型,这是构建任何程序的基础。

1. 基本数据类型:

  • int:整型(Integer)

    • 用于存储整数(没有小数部分的数字),例如:-10, 0, 123
    • 通常占用 4 个字节(32位),可以存储的范围通常为 -231 到 231-1。
    • 注意: 实际大小可能因编译器和操作系统而异,可以使用 sizeof(int) 查看。
  • char:字符型(Character)

    • 用于存储单个字符,例如:'a', 'B', '1', '$'.
    • 通常占用 1 个字节(8位),可以存储 ASCII 码表中的字符。
  • float:单精度浮点型(Floating-point)

    • 用于存储带有小数部分的数值,精度有限。例如:3.14, -0.5, 2.0f (注意 f 后缀)。
    • 通常占用 4 个字节,提供约 7 位有效数字的精度。
  • bool:布尔类型(Boolean)

    • 用于存储逻辑值,只有两个可能的值:true(真)或 false(假)。
    • 通常占用 1 个字节,但实际存储可能只用一个比特位。
  • void:空类型

    • 表示没有值。
    • 主要用于以下两种情况:
      • 函数返回值: 如果函数不返回任何值,则将其返回类型声明为 void
      • 函数参数: 如果函数不接受任何参数,则参数列表可以写为 void 或空着。

2.算术运算符:

  • + 加法:将两个操作数相加。

  • - 减法:将第二个操作数从第一个操作数中减去。

  • * 乘法:将两个操作数相乘。

  • / 除法:将第一个操作数除以第二个操作数。

  • % 取余(模):返回两个整数相除后的余数。

  • sizeof() 大小运算符:用于获取数据类型或变量所占用的内存大小(以字节为单位)。

  • 整数除法的重要特性:

    • 截断行为: 当两个整数进行除法运算时,结果会被截断为整数部分,小数部分会被直接舍弃,不会进行四舍五入。
    • 示例: 7 / 3 的结果是 2,而不是 2.333...
  • 取余运算的应用:

    • 判断整除性: 如果 a % b 的结果为 0,则表示 a 可以被 b 整除。
    • 获取个位数字: n % 10 可以获取整数 n 的个位数字。
    • 循环处理: 常用于循环中,例如限制索引在一定范围内。

3. 其他基本数据类型 (大小和范围可能因系统和编译器而异):

  • short int (简写为 short):短整型

    • 通常占用 2 个字节,存储范围比 int 小,但可以节省内存。
  • long int (简写为 long):长整型

    • 通常占用 4 或 8 个字节,存储范围比 int 大。在现代 64 位系统中,通常为 8 字节。
  • long long int (简写为 long long):更长的整型

    • 通常占用 8 个字节,提供更大的整数存储范围。
  • 浮点型 (精度和范围不同):

    • double:双精度浮点型

      • 精度比 float 更高,可以存储更多位的小数。
      • 通常占用 8 个字节,提供约 15 位有效数字的精度。推荐在需要较高精度的浮点数计算中使用。
    • long double:扩展精度浮点型

      • 提供比 double 更高的精度,但具体大小和精度取决于编译器和平台。
      • 通常占用 10 或 16 个字节
  • 无符号类型(Unsigned):

    • 在整数类型(如 int, short, long, long long, char)前加 unsigned 关键字,表示该类型不存储符号位,只能存储非负数(零和正数)。
    • 优点: 可以扩展正数的表示范围。例如,unsigned int 的正数范围是 int 的两倍。
    • 缺点: 不能存储负数。
    • 示例: unsigned int, unsigned short, unsigned long long, unsigned char

代码示例分析:

c++
#include <iostream>

using namespace std;

int main() {
  // 声明变量并赋值
  int age = 25;
  char initial = 'J';
  float height = 1.75;
  bool isStudent = true;

  // 打印变量值
  cout << "Age: " << age << endl;
  cout << "Initial: " << initial << endl;
  cout << "Height: " << height << endl;
  cout << "Is student? " << isStudent << endl;

  // 算术运算
  int a = 10;
  int b = 3;
  int sum = a + b;
  int difference = a - b;
  int product = a * b;
  int quotient = a / b;
  int remainder = a % b;

  cout << "Sum: " << sum << endl;
  cout << "Difference: " << difference << endl;
  cout << "Product: " << product << endl;
  cout << "Quotient: " << quotient << endl; // 输出 3,因为是整数除法
  cout << "Remainder: " << remainder << endl; // 输出 1

  // 使用 sizeof 运算符
  cout << "Size of age: " << sizeof(age) << " bytes" << endl;
  cout << "Size of float: " << sizeof(float) << " bytes" << endl;

  return 0;
}

代码示例解释:

  • 变量声明和初始化:

    • int age = 25;:声明一个整型变量 age 并赋值为 25
    • char initial = 'J';:声明一个字符型变量 initial 并赋值为字符 'J'
    • float height = 1.75;:声明一个单精度浮点型变量 height 并赋值为 1.75
    • bool isStudent = true;:声明一个布尔类型变量 isStudent 并赋值为 true
  • 使用 cout 打印变量的值:

    • cout << "Age: " << age << endl;:使用 cout 将字符串和变量 age 的值输出到控制台。
  • 算术运算示例:

    • 演示了加、减、乘、除和取余运算。
    • 特别注意 quotient 的结果,展示了整数除法的截断行为。
  • 使用 sizeof 运算符:

    • cout << "Size of age: " << sizeof(age) << " bytes" << endl;:使用 sizeof 运算符获取变量 age 所占用的内存大小,并输出到控制台。这可以帮助我们验证不同数据类型的大小。

总结:

理解 C++ 的基本数据类型及其特性是编写有效和高效 C++ 代码的关键。选择合适的数据类型可以帮助我们节省内存,提高程序的性能,并避免潜在的错误。在后续的课程中,我们将学习更多关于如何使用这些数据类型进行更复杂的操作。

作业:

  1. 温度转换器

    编写一个 C++ 程序,实现华氏温度到摄氏温度的转换。

    • 程序开始时,提示用户输入一个华氏温度值(可以使用 intdouble 类型存储)。
    • 使用以下公式将华氏温度转换为摄氏温度: 摄氏温度 = (华氏温度 - 32) * 5 / 9
    • 将计算得到的摄氏温度值输出到控制台,并注明单位(摄氏度)。
    • 扩展练习(可选): 让程序也能实现摄氏温度到华氏温度的转换。用户可以选择进行哪种转换。

    示例输出:

    请输入华氏温度:68
    对应的摄氏温度为:20 摄氏度
    
    或者 (扩展练习)
    
    请选择转换类型 (1. 华氏转摄氏, 2. 摄氏转华氏):1
    请输入华氏温度:68
    对应的摄氏温度为:20 摄氏度

参考实现如下:

c++
#include <iostream>
#include <iomanip> // 用于设置输出精度

using namespace std;

int main() {
    int choice;
    double temperature, convertedTemperature;

    // 提示用户选择转换类型
    cout << "请选择转换类型 (1. 华氏转摄氏, 2. 摄氏转华氏):";
    cin >> choice;

    if (choice == 1) {
        // 华氏转摄氏
        cout << "请输入华氏温度:";
        cin >> temperature;
        convertedTemperature = (temperature - 32) * 5.0 / 9.0;
        cout << "对应的摄氏温度为:" << fixed << setprecision(2) << convertedTemperature << " 摄氏度" << endl;
    } else if (choice == 2) {
        // 摄氏转华氏
        cout << "请输入摄氏温度:";
        cin >> temperature;
        convertedTemperature = (temperature * 9.0 / 5.0) + 32;
        cout << "对应的华氏温度为:" << fixed << setprecision(2) << convertedTemperature << " 华氏度" << endl;
    } else {
        cout << "无效的选择,请重新运行程序。" << endl;
    }

    return 0;
}