C++ 基础学习笔记
适合目标:从零到能看懂常见 C++ 代码,能应对校招八股、算法题环境和基础工程开发。
学习重点:语法基础、指针与引用、类与对象、内存管理、STL、文件与输入输出。
学习原则:先建立“值、对象、生命周期”这条主线,再去记语法细节。
目录
- 学习总览
- C++ 在学什么
- 基础语法
- 函数
- 指针、引用与 const
- 类与对象
- 构造、析构与拷贝
- 内存管理
- STL 基础
- 输入输出与文件
- 常见面试题
- 学习建议
- 一页速记总结
1. 学习总览
很多人第一次学 C++ 会觉得它又像 C、又像 Java,还混着一堆符号。
真正要抓住的不是“语法有多杂”,而是下面三件事:
- 一个值存在哪里
- 一个对象什么时候创建、什么时候销毁
- 一段代码有没有额外的拷贝、分配和资源开销
如果这三件事能想明白,后面的类、指针、容器、面试题都会更顺。
2. C++ 在学什么
可以把 C++ 理解成一门同时强调下面几件事的语言:
- 接近底层,能直接管理内存和资源
- 支持面向对象,能做复杂模块设计
- 支持泛型,能写可复用的模板代码
- 兼顾性能,很多工程场景会优先考虑它
校招里常见的使用场景:
- 算法题默认语言之一
- 后台高性能服务
- 音视频、游戏、图形学、客户端
- 中间件、编译器、数据库
3. 基础语法
3.1 变量与类型
常见基础类型:
intlong longdoublecharbool
int age = 20;
long long count = 1000000000;
double score = 98.5;
char grade = 'A';
bool ok = true;
3.2 判断与循环
if (age >= 18) {
cout << "adult" << endl;
}
for (int i = 0; i < 5; i++) {
cout << i << endl;
}
3.3 字符串
std::string 比 C 风格字符串更常用。
string name = "cpp";
name += " study";
cout << name.size() << endl;
3.4 命名空间
using namespace std;
面试和工程里更推荐显式写:
std::string name = "tom";
std::cout << name << std::endl;
原因:
- 可读性更清楚
- 避免命名冲突
4. 函数
4.1 基本形式
int add(int a, int b) {
return a + b;
}
4.2 参数传递方式
常见有三种:
- 值传递
- 引用传递
- 指针传递
void swapValue(int a, int b) {}
void swapRef(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
理解重点:
- 值传递会拷贝一份参数
- 引用传递常用于修改原对象或避免大对象拷贝
- 指针传递更灵活,但使用成本更高
4.3 函数重载
同名函数,参数列表不同。
int sum(int a, int b) {
return a + b;
}
double sum(double a, double b) {
return a + b;
}
5. 指针、引用与 const
这一部分几乎是 C++ 基础的分水岭。
5.1 指针
指针存的是地址。
int x = 10;
int* p = &x;
cout << *p << endl;
要看懂这几个符号:
&x表示取地址int* p表示p是一个指针*p表示解引用,取出地址指向的值
5.2 引用
引用可以理解成变量别名。
int x = 10;
int& ref = x;
ref = 20;
这里 ref 改了,x 也会改。
5.3 指针和引用区别
- 指针可以为空,引用通常不能为空
- 指针可以改为指向别的对象,引用绑定后通常不改
- 引用语法更自然,常用于参数传递
5.4 const
const int x = 10;
const int* p1 = &x;
int* const p2 = nullptr;
高频理解:
const int*是“指向常量的指针”int* const是“常量指针”const int* const两边都不能改
6. 类与对象
6.1 类的基本形式
class Student {
public:
string name;
int age;
void sayHello() {
cout << "hello " << name << endl;
}
};
Student s;
s.name = "alice";
s.age = 20;
s.sayHello();
6.2 访问权限
public外部可访问private只能类内部访问protected主要和继承相关
6.3 封装
class Counter {
private:
int value = 0;
public:
void increment() {
value++;
}
int getValue() const {
return value;
}
};
封装的意义:
- 隐藏内部实现
- 保护数据合法性
- 降低模块耦合
7. 构造、析构与拷贝
7.1 构造函数
对象创建时调用。
class User {
public:
string name;
User(string n) : name(n) {}
};
7.2 析构函数
对象销毁时调用。
class FileWrapper {
public:
~FileWrapper() {
cout << "release resource" << endl;
}
};
7.3 拷贝构造
class Demo {
public:
Demo() {}
Demo(const Demo& other) {}
};
常见触发场景:
- 用一个对象初始化另一个对象
- 函数值传递对象
- 函数返回对象
7.4 为什么要关注拷贝
如果类里管理了堆内存、文件句柄、锁等资源,默认拷贝可能出问题:
- 浅拷贝
- 重复释放
- 资源悬空
8. 内存管理
8.1 栈和堆
int a = 10; // 栈
int* p = new int(20); // 堆
delete p;
区别可以先这样理解:
- 栈对象生命周期通常跟作用域绑定
- 堆对象需要手动管理
- 堆更灵活,但更容易泄漏
8.2 new 和 delete
int* p = new int(5);
delete p;
p = nullptr;
数组要配套用:
int* arr = new int[10];
delete[] arr;
8.3 内存问题高频类型
- 内存泄漏
- 野指针
- 悬空指针
- 重复释放
面试时最常问的一个点是:
为什么现代 C++ 不建议到处手写 new 和 delete?
因为人工管理资源太容易出错,所以更推荐 RAII 和智能指针。
9. STL 基础
9.1 vector
最常用动态数组。
vector<int> nums = {1, 2, 3};
nums.push_back(4);
cout << nums[0] << endl;
常见操作:
push_backpop_backsizeempty
9.2 string
string s = "hello";
s += " world";
cout << s.substr(0, 5) << endl;
9.3 pair
pair<int, string> p = {1, "one"};
9.4 map 和 unordered_map
map<string, int> mp;
mp["apple"] = 3;
unordered_map<string, int> ump;
ump["banana"] = 5;
区别:
map底层通常是红黑树,有序unordered_map底层通常是哈希表,无序
9.5 set 和 unordered_set
用于去重、查找。
10. 输入输出与文件
10.1 标准输入输出
int n;
cin >> n;
cout << n << endl;
10.2 文件读写
#include <fstream>
ofstream out("test.txt");
out << "hello";
out.close();
ifstream in("test.txt");
string line;
getline(in, line);
in.close();
11. 常见面试题
11.1 指针和引用的区别
答题主线:
- 指针本质是地址变量,引用本质是别名
- 指针可为空,可改指向
- 引用定义时必须初始化,使用更像普通变量
11.2 栈和堆的区别
答题主线:
- 管理方式不同
- 生命周期不同
- 分配效率和灵活性不同
11.3 new/delete 和 malloc/free 区别
答题主线:
new/delete是运算符,malloc/free是函数new会调用构造函数,delete会调用析构函数malloc只分配原始内存,不做对象初始化
11.4 vector 和数组区别
答题主线:
vector可动态扩容- 自带边界相关接口和丰富算法支持
- 数组更原始,长度通常固定
12. 学习建议
推荐按这个节奏学:
- 先把变量、函数、引用、类跑通
- 再重点理解构造析构、拷贝、内存管理
- 然后刷
vector、string、map常见题 - 最后开始补 RAII、智能指针、模板、移动语义
如果你的目标是面试,不要只背定义,要会说:
- 这个机制解决什么问题
- 如果不会它,代码容易出什么 bug
- 工程里一般怎么用
13. 一页速记总结
- C++ 基础主线是对象、资源、生命周期
- 指针解决“地址与间接访问”,引用解决“别名与高效传参”
- 类是封装数据与行为,对象是类的实例
- 构造函数负责初始化,析构函数负责清理
- 堆内存灵活但危险,优先减少手写
new/delete vector、string、map是最常见 STL 基础容器- 面试答题不要只报概念,要带场景和风险