Ch 4: 第一个 C++ 程序详解
- 理解 C++ 程序的基本结构
- 掌握
main()函数的规范 - 理解
#include和预处理器 - 熟悉编译和运行流程
- 理解命名空间的概念
4.1 最简单的 C++ 程序
Section titled “4.1 最简单的 C++ 程序”4.1.1 Hello World 对比
Section titled “4.1.1 Hello World 对比”Python 版本:
print("Hello, World!")C++ 版本:
#include <iostream>
int main() { std::cout << "Hello, World!" << std::endl; return 0;}4.1.2 逐行解析
Section titled “4.1.2 逐行解析”// 第 1 行:注释// 注释不会被编译,用于人类阅读// C++ 有两种注释:// - 单行注释:// 到行尾// - 多行注释:/* ... */
// 第 2 行:预处理器指令#include <iostream>// #include 告诉编译器"包含" iostream 文件的内容// iostream 包含 std::cout、std::cin 等输入输出功能// 类似 Python 的 import,但工作方式不同
// 第 4 行:主函数 - 程序入口int main() {// int = 返回类型(整数)// main = 函数名(特殊:程序入口)// () = 空参数列表
// 第 5 行:输出语句 std::cout << "Hello, World!" << std::endl; // std::cout = 标准输出流(屏幕) // << = 流插入运算符(把数据"插入"到流中) // "..." = 字符串字面量 // std::endl = 换行 + 刷新缓冲区 // ; = 语句结束符(C++ 每条语句以分号结尾)
// 第 6 行:返回 return 0; // 0 = 返回值给操作系统 // 0 表示"程序正常结束" // 非 0 表示"出错"}4.2 main() 函数详解
Section titled “4.2 main() 函数详解”main() 是每个 C++ 程序的入口点,操作系统通过调用 main() 来运行你的程序。
4.2.1 标准签名
Section titled “4.2.1 标准签名”// 1. 最简形式(不接受参数)int main() { return 0;}
// 2. 带命令行参数(类似 sys.argv)int main(int argc, char* argv[]) { // argc = 参数个数 // argv = 参数数组 // argv[0] = 程序名 // argv[1] = 第一个参数 // ... return 0;}
// 3. 使用 std::vector 风格的 argv(C++20)int main(int argc, char* argv[]) { for (int i = 0; i < argc; ++i) { std::cout << "argv[" << i << "]: " << argv[i] << std::endl; } return 0;}4.2.2 命令行参数示例
Section titled “4.2.2 命令行参数示例”#include <iostream>#include <string>
int main(int argc, char* argv[]) { std::cout << "程序名: " << argv[0] << std::endl;
for (int i = 1; i < argc; ++i) { std::cout << "参数 " << i << ": " << argv[i] << std::endl; }
std::cout << "共 " << argc << " 个参数" << std::endl;
return 0;}# 编译运行g++ -std=c++20 args.cpp -o args./args hello world 42
# 输出:# 程序名: ./args# 参数 1: hello# 参数 2: world# 参数 3: 42# 共 4 个参数4.2.3 main 的返回值
Section titled “4.2.3 main 的返回值”#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
int main() { // 两种成功退出方式(等价) return 0; // return EXIT_SUCCESS;
// 失败时返回非零值 // return 1; // return EXIT_FAILURE;}4.3 #include 和预处理器
Section titled “4.3 #include 和预处理器”4.3.1 预处理器的工作原理
Section titled “4.3.1 预处理器的工作原理”Python 的 import 在运行时工作,C++ 的 #include 在编译前(预处理阶段)工作:
// 你写的代码:#include <iostream>int main() { std::cout << "hello";}
// 预处理器展开后(大概是这样):// iostream 的全部内容被"复制粘贴"到这里// 然后编译器处理展开后的代码4.3.2 尖括号 vs 双引号
Section titled “4.3.2 尖括号 vs 双引号”#include <iostream> // 系统头文件,编译器查找系统目录#include "myheader.h" // 本项目头文件,查找当前目录和指定目录#include "../include/utils.h" // 相对路径#include "/full/path/to/header.h" // 绝对路径(不推荐)4.3.3 头文件的结构
Section titled “4.3.3 头文件的结构”// utils.h - 头文件#ifndef UTILS_H // 头文件保护宏(防止重复包含)#define UTILS_H
// 函数声明int add(int a, int b);double square(double x);
// 内联函数inline int double_value(int x) { return x * 2;}
// 类声明class Calculator {public: int add(int a, int b);};
#endif // UTILS_H// utils.cpp - 实现文件#include "utils.h"
int add(int a, int b) { return a + b;}
double square(double x) { return x * x;}
int Calculator::add(int a, int b) { return a + b;}4.3.4 预处理器宏
Section titled “4.3.4 预处理器宏”// 定义常量#define PI 3.14159#define MAX_SIZE 100
// 条件编译#ifdef DEBUG std::cout << "Debug mode" << std::endl;#else std::cout << "Release mode" << std::endl;#endif
// 现代 C++ 推荐用 const/constexpr 而不是 #defineconstexpr double PI = 3.14159; // 类型安全,有作用域4.4 命名空间 std::
Section titled “4.4 命名空间 std::”4.4.1 什么是命名空间
Section titled “4.4.1 什么是命名空间”命名空间是 C++ 组织代码的方式,防止名字冲突:
# Python - 模块避免冲突import collectionsimport mycollections
collections.defaultdict() # 标准库mycollections.defaultdict() # 你的代码// C++ - 命名空间namespace std { // 标准库的所有东西都在 std 命名空间 class ostream; class istream;}
namespace myproject { class vector { /* 不会和 std::vector 冲突 */ };}4.4.2 std:: 的使用
Section titled “4.4.2 std:: 的使用”#include <iostream> // std::cout 在 iostream 中定义
int main() { // 完全限定名 std::cout << "Hello" << std::endl;
// using 声明 - 引入单个名字 using std::cout; using std::endl; cout << "Hello" << endl;
// using 命名空间 - 引入整个命名空间(慎用!) using namespace std; // 在大型项目中可能造成名字冲突 cout << "Hello" << endl;
return 0;}4.4.3 嵌套命名空间(C++17)
Section titled “4.4.3 嵌套命名空间(C++17)”// C++17 嵌套命名空间语法namespace myproject::utils::math { int add(int a, int b) { return a + b; }}
// 等价于namespace myproject { namespace utils { namespace math { int add(int a, int b) { return a + b; } } }}
// 使用int main() { myproject::utils::math::add(1, 2);}4.5 iostream 详解
Section titled “4.5 iostream 详解”4.5.1 基本输入输出
Section titled “4.5.1 基本输入输出”#include <iostream>
int main() { // 输出 std::cout << "Hello"; // 字符串 std::cout << 42; // 整数 std::cout << 3.14; // 浮点数 std::cout << 'A'; // 字符 std::cout << true; // 布尔值(输出 1)
// 连续输出 std::cout << "Value: " << 42 << std::endl;
// 输入 int age; std::cin >> age; // 从键盘读取整数到 age
std::string name; std::cin >> name; // 读取字符串(空格分隔)
// 连续读取 int x, y; std::cin >> x >> y; // 读取两个整数
return 0;}4.5.2 endl vs “\n”
Section titled “4.5.2 endl vs “\n””// endl = 换行 + 刷新缓冲区std::cout << "First line" << std::endl;std::cout << "Second line" << std::endl;
// "\n" = 只是换行,不刷新std::cout << "First line\n";std::cout << "Second line\n";
// 什么时候用 endl?// 当你需要立即看到输出时(如调试)// 性能敏感时用 "\n",因为刷新缓冲区有开销4.5.3 格式化输出
Section titled “4.5.3 格式化输出”#include <iostream>#include <iomanip> // 格式化控制
int main() { // 整数进制 int n = 255; std::cout << std::dec << n << std::endl; // 255 std::cout << std::hex << n << std::endl; // ff std::cout << std::oct << n << std::endl; // 377
// 浮点数精度 double pi = 3.14159265; std::cout << std::setprecision(4) << pi << std::endl; // 3.142 std::cout << std::fixed << std::setprecision(2) << pi << std::endl; // 3.14
// 宽度和对齐 std::cout << std::setw(10) << std::left << "hello" << std::endl; std::cout << std::setw(10) << std::right << "world" << std::endl;
return 0;}4.6 注释
Section titled “4.6 注释”// 单行注释 - // 到行尾// 这是注释,不会被编译
/* * 多行注释 * 可以跨行 */
/** * 文档注释 * 用于生成文档 * Doxygen 等工具会处理 */
// C++ 没有 Python 的 """ 三引号注释// 但可以用 /* */ 模拟/* This is a multi-line comment in C++ */4.7 编译流程详解
Section titled “4.7 编译流程详解”4.7.1 四阶段编译模型
Section titled “4.7.1 四阶段编译模型”源代码 (hello.cpp) │ ▼ 1. 预处理 (Preprocessing)预处理文件 (hello.ii/hello.i) │ ▼ 2. 编译 (Compilation)汇编文件 (hello.s) │ ▼ 3. 汇编 (Assembly)目标文件 (hello.o/hello.obj) │ ▼ 4. 链接 (Linking)可执行文件 (hello/hello.exe)4.7.2 分步执行
Section titled “4.7.2 分步执行”# 1. 预处理g++ -E hello.cpp -o hello.i# 展开 #include, #define 等
# 2. 编译到汇编g++ -S hello.i -o hello.s# 生成汇编代码
# 3. 汇编到目标文件g++ -c hello.cpp -o hello.o# 生成机器码(未链接)
# 4. 链接g++ hello.o -o hello# 链接库函数,生成可执行文件4.7.3 目标文件和链接
Section titled “4.7.3 目标文件和链接”int add(int a, int b);
// utils.cpp#include "utils.h"int add(int a, int b) { return a + b;}
// main.cpp#include <iostream>#include "utils.h"
int main() { std::cout << add(1, 2) << std::endl; return 0;}# 分别编译g++ -c utils.cpp -o utils.og++ -c main.cpp -o main.o
# 链接g++ main.o utils.o -o program4.8 完整示例:交互式程序
Section titled “4.8 完整示例:交互式程序”#include <iostream>#include <string>#include <vector>#include <iomanip>
int main() { // 欢迎信息 std::cout << "====================================" << std::endl; std::cout << " 个人信息收集程序" << std::endl; std::cout << "====================================" << std::endl;
// 收集姓名 std::cout << "\n请输入你的姓名: "; std::string name; std::getline(std::cin, name); // 读取整行,包括空格
// 收集年龄 std::cout << "请输入你的年龄: "; int age; std::cin >> age;
// 收集城市 std::cout << "请输入你所在城市: "; std::string city; std::cin >> city;
// 显示收集的信息 std::cout << "\n------------------------------------" << std::endl; std::cout << " 信息确认" << std::endl; std::cout << "------------------------------------" << std::endl; std::cout << std::left; std::cout << std::setw(10) << "姓名:" << name << std::endl; std::cout << std::setw(10) << "年龄:" << age << std::endl; std::cout << std::setw(10) << "城市:" << city << std::endl;
// 简单判断 if (age >= 18) { std::cout << "\n你是一个成年人。" << std::endl; } else { std::cout << "\n你是一个未成年人。" << std::endl; }
std::cout << "感谢使用!" << std::endl;
return 0;}编译运行:
g++ -std=c++20 -o greet greet.cpp./greet
# 输出:# ====================================# 个人信息收集程序# ====================================## 请输入你的姓名: Alice Wang# 请输入你的年龄: 25# 请输入你所在城市: Beijing## ------------------------------------# 信息确认# ------------------------------------# 姓名: Alice Wang# 年龄: 25# 城市: Beijing## 你是一个成年人。# 感谢使用!- C++ 程序从
main()开始执行 #include在预处理时展开内容std::cout和<<用于输出std::cin和>>用于输入- 编译四步:预处理 → 编译 → 汇编 → 链接
return 0表示程序正常结束- 命名空间
std::组织标准库代码
下章预告:ch05 学习 C++ 的变量声明、基本类型和类型系统。