文章目录

C++ 基础学习笔记

适合目标:从零到能看懂常见 C++ 代码,能应对校招八股、算法题环境和基础工程开发。
学习重点:语法基础、指针与引用、类与对象、内存管理、STL、文件与输入输出。
学习原则:先建立“值、对象、生命周期”这条主线,再去记语法细节。


目录

  1. 学习总览
  2. C++ 在学什么
  3. 基础语法
  4. 函数
  5. 指针、引用与 const
  6. 类与对象
  7. 构造、析构与拷贝
  8. 内存管理
  9. STL 基础
  10. 输入输出与文件
  11. 常见面试题
  12. 学习建议
  13. 一页速记总结

1. 学习总览

很多人第一次学 C++ 会觉得它又像 C、又像 Java,还混着一堆符号。

真正要抓住的不是“语法有多杂”,而是下面三件事:

  1. 一个值存在哪里
  2. 一个对象什么时候创建、什么时候销毁
  3. 一段代码有没有额外的拷贝、分配和资源开销

如果这三件事能想明白,后面的类、指针、容器、面试题都会更顺。


2. C++ 在学什么

可以把 C++ 理解成一门同时强调下面几件事的语言:

  1. 接近底层,能直接管理内存和资源
  2. 支持面向对象,能做复杂模块设计
  3. 支持泛型,能写可复用的模板代码
  4. 兼顾性能,很多工程场景会优先考虑它

校招里常见的使用场景:

  1. 算法题默认语言之一
  2. 后台高性能服务
  3. 音视频、游戏、图形学、客户端
  4. 中间件、编译器、数据库

3. 基础语法

3.1 变量与类型

常见基础类型:

  1. int
  2. long long
  3. double
  4. char
  5. bool
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;

原因:

  1. 可读性更清楚
  2. 避免命名冲突

4. 函数

4.1 基本形式

int add(int a, int b) {
  return a + b;
}

4.2 参数传递方式

常见有三种:

  1. 值传递
  2. 引用传递
  3. 指针传递
void swapValue(int a, int b) {}

void swapRef(int& a, int& b) {
  int temp = a;
  a = b;
  b = temp;
}

理解重点:

  1. 值传递会拷贝一份参数
  2. 引用传递常用于修改原对象或避免大对象拷贝
  3. 指针传递更灵活,但使用成本更高

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;

要看懂这几个符号:

  1. &x 表示取地址
  2. int* p 表示 p 是一个指针
  3. *p 表示解引用,取出地址指向的值

5.2 引用

引用可以理解成变量别名。

int x = 10;
int& ref = x;
ref = 20;

这里 ref 改了,x 也会改。

5.3 指针和引用区别

  1. 指针可以为空,引用通常不能为空
  2. 指针可以改为指向别的对象,引用绑定后通常不改
  3. 引用语法更自然,常用于参数传递

5.4 const

const int x = 10;
const int* p1 = &x;
int* const p2 = nullptr;

高频理解:

  1. const int* 是“指向常量的指针”
  2. int* const 是“常量指针”
  3. 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 访问权限

  1. public 外部可访问
  2. private 只能类内部访问
  3. protected 主要和继承相关

6.3 封装

class Counter {
private:
  int value = 0;

public:
  void increment() {
    value++;
  }

  int getValue() const {
    return value;
  }
};

封装的意义:

  1. 隐藏内部实现
  2. 保护数据合法性
  3. 降低模块耦合

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) {}
};

常见触发场景:

  1. 用一个对象初始化另一个对象
  2. 函数值传递对象
  3. 函数返回对象

7.4 为什么要关注拷贝

如果类里管理了堆内存、文件句柄、锁等资源,默认拷贝可能出问题:

  1. 浅拷贝
  2. 重复释放
  3. 资源悬空

8. 内存管理

8.1 栈和堆

int a = 10;           // 栈
int* p = new int(20); // 堆
delete p;

区别可以先这样理解:

  1. 栈对象生命周期通常跟作用域绑定
  2. 堆对象需要手动管理
  3. 堆更灵活,但更容易泄漏

8.2 new 和 delete

int* p = new int(5);
delete p;
p = nullptr;

数组要配套用:

int* arr = new int[10];
delete[] arr;

8.3 内存问题高频类型

  1. 内存泄漏
  2. 野指针
  3. 悬空指针
  4. 重复释放

面试时最常问的一个点是:

为什么现代 C++ 不建议到处手写 newdelete

因为人工管理资源太容易出错,所以更推荐 RAII 和智能指针。


9. STL 基础

9.1 vector

最常用动态数组。

vector<int> nums = {1, 2, 3};
nums.push_back(4);
cout << nums[0] << endl;

常见操作:

  1. push_back
  2. pop_back
  3. size
  4. empty

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;

区别:

  1. map 底层通常是红黑树,有序
  2. 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 指针和引用的区别

答题主线:

  1. 指针本质是地址变量,引用本质是别名
  2. 指针可为空,可改指向
  3. 引用定义时必须初始化,使用更像普通变量

11.2 栈和堆的区别

答题主线:

  1. 管理方式不同
  2. 生命周期不同
  3. 分配效率和灵活性不同

11.3 new/deletemalloc/free 区别

答题主线:

  1. new/delete 是运算符,malloc/free 是函数
  2. new 会调用构造函数,delete 会调用析构函数
  3. malloc 只分配原始内存,不做对象初始化

11.4 vector 和数组区别

答题主线:

  1. vector 可动态扩容
  2. 自带边界相关接口和丰富算法支持
  3. 数组更原始,长度通常固定

12. 学习建议

推荐按这个节奏学:

  1. 先把变量、函数、引用、类跑通
  2. 再重点理解构造析构、拷贝、内存管理
  3. 然后刷 vectorstringmap 常见题
  4. 最后开始补 RAII、智能指针、模板、移动语义

如果你的目标是面试,不要只背定义,要会说:

  1. 这个机制解决什么问题
  2. 如果不会它,代码容易出什么 bug
  3. 工程里一般怎么用

13. 一页速记总结

  1. C++ 基础主线是对象、资源、生命周期
  2. 指针解决“地址与间接访问”,引用解决“别名与高效传参”
  3. 类是封装数据与行为,对象是类的实例
  4. 构造函数负责初始化,析构函数负责清理
  5. 堆内存灵活但危险,优先减少手写 new/delete
  6. vectorstringmap 是最常见 STL 基础容器
  7. 面试答题不要只报概念,要带场景和风险