第一部分:快速上手 —— 建立 C++ 基本语法与编程范式

第一部分:快速上手 ------ 建立 C++ 基本语法与编程范式

目标 :在 2~3 天内掌握能独立编写简单 C++ 程序的核心语法,同时养成「内存与性能」的工程意识。

学习方法:每学一个知识点,立刻动手写几行代码验证,并思考"这个特性在内存里发生了什么"。


1.1 Hello World 与编译流程

第一个程序

cpp

复制代码
#include <iostream>   // 预处理器指令,引入输入输出库

int main() {          // 程序入口,操作系统调用此函数
    std::cout << "Hello, C++!" << std::endl;
    return 0;         // 返回 0 表示成功
}

编译与运行

  • 保存为 hello.cpp

  • 编译(使用 g++):

    bash

    复制代码
    g++ -std=c++17 -o hello hello.cpp
    • -std=c++17:指定 C++ 标准(推荐用最新)

    • -o hello:指定输出可执行文件名

  • 运行./hello(Linux/Mac)或 hello.exe(Windows)

编译的四个阶段(本质理解)

  1. 预处理 :处理 #include、宏等,生成 .i 文件

  2. 编译 :将预处理后的代码翻译为汇编语言,生成 .s

  3. 汇编 :将汇编转为机器码,生成 .o(目标文件)

  4. 链接 :将多个 .o 和库文件合并为最终可执行文件

重点 :每个 .cpp 文件独立编译为 .o,再链接成可执行文件。头文件(.h)只是声明,不参与编译。


1.2 基础数据类型、变量与运算符

基本内置类型

类型 字节(常见) 范围 备注
bool 1 true/false 任何非零值转为 true
char 1 -128~127 或 0~255 用于字符或小整数
int 4 -2³¹ ~ 2³¹-1 最常用整数
float 4 约 1e-38 ~ 1e38 单精度浮点
double 8 约 1e-308 ~ 1e308 双精度浮点(默认)
void 无值 用于函数无返回值

注意:char 可能有符号也可能无符号,取决于编译器,若需明确用 signed char / unsigned char

变量声明与初始化

cpp

复制代码
int a = 10;          // 拷贝初始化
int b(20);           // 直接初始化
int c{30};           // 列表初始化(C++11,更安全,防止窄化转换)
auto d = 3.14;       // auto 自动推导为 double
const int e = 100;   // 常量,不可修改
auto 的本质

auto编译期类型占位符 ,编译器根据初始化表达式推导出实际类型,生成的代码与显式写出类型完全相同,无运行时开销

运算符

  • 算术:+ - * / %(整数除法取整,% 仅整数)

  • 关系:== != < > <= >=

  • 逻辑:&& || !(短路求值)

  • 位运算:& | ^ ~ << >>(操作二进制位)

  • 赋值:= += -= *= /=

  • 自增/自减:++ --(前缀先变后用,后缀先用后变)


1.3 流程控制与函数

条件语句

cpp

复制代码
// if-else
int score = 85;
if (score >= 90) {
    std::cout << "A";
} else if (score >= 80) {
    std::cout << "B";
} else {
    std::cout << "C";
}

// switch(仅整型/枚举)
switch (grade) {
    case 'A': std::cout << "Excellent"; break;
    case 'B': std::cout << "Good"; break;
    default: std::cout << "Try harder";
}

循环

cpp

复制代码
// for 循环(经典)
for (int i = 0; i < 10; ++i) {
    std::cout << i << " ";
}

// while 循环
int n = 5;
while (n > 0) {
    std::cout << n--;
}

// 基于范围的 for 循环(C++11,配合容器)
int arr[] = {1, 2, 3};
for (int x : arr) {
    std::cout << x;
}

函数

cpp

复制代码
// 函数重载:同名不同参数
int max(int a, int b) {
    return (a > b) ? a : b;
}
double max(double a, double b) {
    return (a > b) ? a : b;
}

// 默认参数(必须从右向左提供)
void print(int x, int times = 1) {
    for (int i = 0; i < times; ++i) std::cout << x << " ";
}

// 内联函数(建议,编译器可忽略)
inline int square(int x) { return x * x; }
内联的本质

inline 只是向编译器发出请求,希望将函数体在调用点展开,以减少函数调用开销。但编译器会根据优化级别和函数大小决定是否内联。现代编译器在 -O2 下会自动内联简短函数。


1.4 类与对象(核心)

C++ 是面向对象语言, 是用户自定义类型,对象是类的实例。

定义一个简单类

cpp

复制代码
class Student {
private:                // 私有成员,只能被类内部访问
    std::string name;
    int age;
public:                 // 公有接口
    // 构造函数(无返回值,与类同名)
    Student(const std::string& n, int a) : name(n), age(a) {}
    
    // 成员函数
    void introduce() const {
        std::cout << "I'm " << name << ", " << age << " years old.\n";
    }
    
    // 析构函数(对象销毁时自动调用,用于释放资源)
    ~Student() {
        // 一般在这里释放动态分配的内存(但本例没有)
    }
};

使用对象

cpp

复制代码
int main() {
    Student s1("Alice", 20);  // 栈上构造
    s1.introduce();
    
    Student* s2 = new Student("Bob", 22);  // 堆上构造(需要手动 delete)
    s2->introduce();
    delete s2;                // 务必释放
    return 0;
}

RAII 思想(资源获取即初始化)

本质 :利用对象的生命周期管理资源(内存、文件句柄、锁等)。资源在构造函数中获取,在析构函数中释放。这样当对象离开作用域时,资源自动释放,即使发生异常也能保证释放,这是 C++ 最核心的编程范式。

示例:如果我们使用 std::fstream 打开文件,文件在析构时自动关闭,无需手动 close()


1.5 标准库入门

C++ 标准库提供了丰富的数据结构和算法,我们只需掌握最常用的几个。

输入输出(iostream)

cpp

复制代码
#include <iostream>
using namespace std; // 可省略 std::,但不推荐在头文件或大型项目使用

int main() {
    int x;
    cout << "Enter a number: ";
    cin >> x;                     // 从键盘读入
    cerr << "Error message";      // 标准错误输出
    return 0;
}

字符串(std::string)

cpp

复制代码
#include <string>
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + " " + s2;   // 拼接
std::cout << s3.size() << std::endl; // 长度(字符数,非字节)
if (s1 == "Hello") { /* ... */ }

容器 ------ vector(动态数组)

cpp

复制代码
#include <vector>
std::vector<int> v;               // 空 vector
v.push_back(10);                  // 尾部添加
v.push_back(20);
v[0] = 100;                       // 下标访问(不检查越界)
for (int i = 0; i < v.size(); ++i) {
    std::cout << v[i] << " ";
}
for (int x : v) {                 // 范围 for
    std::cout << x << " ";
}
vector 的简单本质

vector 是动态数组,内部在堆上分配连续内存。当空间不足时,它会重新分配一块更大的内存(通常为当前容量的 2 倍或 1.5 倍),将旧元素复制/移动到新内存,然后释放旧内存。这个过程是自动 的,但需要注意迭代器失效问题(插入/删除可能导致所有迭代器失效)。

容器 ------ map(关联数组)

cpp

复制代码
#include <map>
std::map<std::string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;
for (auto& pair : scores) {       // pair 是 std::pair<const std::string, int>
    std::cout << pair.first << ": " << pair.second << std::endl;
}

map 底层是红黑树(平衡二叉搜索树),按键有序,插入/查找/删除复杂度 O(log n)。


1.6 内存分区与变量生命周期(重中之重

为了深刻理解 C++,必须明白程序运行时内存如何划分。

区域 存储内容 生命周期 分配/释放
栈(Stack) 局部变量、函数参数、返回地址 函数调用时分配,返回时自动释放 编译器自动管理,速度极快
堆(Heap) 动态分配的对象(new/malloc newdelete,由程序员控制 手动管理,速度慢,可能产生内存碎片
静态存储区 全局变量、static 变量 程序启动分配,结束释放 编译器自动管理
常量存储区 字符串字面量、const 全局常量 程序启动到结束 通常只读,可能放在代码段

示例分析

cpp

复制代码
int global = 10;              // 静态存储区

void func() {
    int local = 20;           // 栈
    static int static_local = 30; // 静态存储区(只初始化一次)
    int* heap_ptr = new int(40); // 堆
    delete heap_ptr;          // 必须手动释放
}

关键理解 :栈上对象超出作用域自动调用析构函数,堆上对象必须显式 delete 才会调用析构。忘记 delete 会导致内存泄漏


1.7 练习与巩固

  1. 练习 1:编写一个程序,从标准输入读取两个整数,输出它们的和、差、积、商(整数除法)。

  2. 练习 2 :定义一个 Circle 类,有半径 radius 成员,提供计算面积和周长的成员函数。在 main 中创建对象并测试。

  3. 练习 3 :使用 vector 存储 10 个随机整数(可用 rand()),然后遍历输出,并计算总和与平均值。

  4. 思考题 :如果在函数内创建了一个 vector 对象,当函数返回后,这个 vector 占用的内存是否自动释放?为什么?(提示:RAII)


第一部分总结

你已完成快速入门,掌握了:

  • 编译流程和基本语法

  • 类与对象的定义和使用,以及 RAII 思想

  • 常用标准库组件

  • 内存分区和变量生命周期

接下来,我们将进入第二部分,深入探讨 C++ 的内存模型、拷贝控制、移动语义、多态实现等本质原理。


面试问 :"你如何理解 C++ 和 Java 的内存管理差异?"

回答框架:C++ 提供手动和自动(RAII)两种方式,性能可控且无垃圾回收开销;Java 依赖垃圾收集器,编程更简单但可能停顿。C++ 给予程序员更多控制权,也要求更谨慎。

相关推荐
郝学胜-神的一滴17 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
bksczm17 小时前
linux之线程概念和控制
linux·开发语言·c++
JackieZhengChina17 小时前
零依赖轻量级JS悬浮提示插件title2tip-js的使用教程
开发语言·javascript·ecmascript
hehelm17 小时前
Linux网络编程—TCP字典翻译系统
linux·开发语言·网络·c++·tcp/ip
hansang_IR18 小时前
【记录】「SCOI2016」三道模拟赛/26.7.12
c++·算法
李永奉18 小时前
杰理可视化SDK开发-【BUG】配置“TWS两边同时按消息使能”功能后,按键单击功能无效失灵
开发语言·单片机·嵌入式硬件·物联网·bug
会周易的程序员18 小时前
从零构建多核CPU负载自适应控制系统
linux·c++·笔记·物联网·测试工具
m0_6174939419 小时前
Python OpenCV 透视变换(Perspective Transform)详解与实战
开发语言·python·opencv
程序猿编码19 小时前
用C++从零开始造一个微型GPT,不借助任何第三方库
开发语言·c++·gpt·模型推理