C++ 是一门广泛应用于高性能计算、游戏开发、嵌入式系统和底层系统编程的语言
- ✅ **异常安全**:无论是否发生异常,资源都能被释放。- ✅ **代码简洁**:无需在多处写 `delete` 或 `close()`。- ✅ **避免资源泄漏**:只要对象是局部变量或成员变量,就能保证析构。- ✅ **通用性强**:可用于内存、锁、socket、GUI 句柄等所有资源。
C++ 是一门广泛应用于高性能计算、游戏开发、嵌入式系统和底层系统编程的语言。其核心优势在于对内存的精细控制和接近硬件的操作能力。以下是围绕你提供的“核心学习路径”进行的详细解析与实战示例。
1. 基础语法
变量与数据类型
int a = 10;
double b = 3.14;
char c = 'A';
bool flag = true;
指针与引用
int x = 5;
int* ptr = &x; // 指针指向x的地址
int& ref = x; // 引用,ref是x的别名
(*ptr)++; // x变为6
ref++; // x变为7
流程控制
if (a > 5) {
cout << "a is greater than 5\n";
} else {
cout << "a is not greater than 5\n";
}
for (int i = 0; i < 5; ++i) {
cout << i << " ";
}
类与对象、继承 / 多态
class Animal {
public:
virtual void speak() { cout << "Animal speaks\n"; }
};
class Dog : public Animal {
public:
void speak() override { cout << "Woof!\n"; } // 多态实现
};
// 使用
Animal* pet = new Dog();
pet->speak(); // 输出: Woof!
delete pet;
2. 核心特性
STL 容器:vector 和 map
#include <vector>
#include <map>
#include <iostream>
using namespace std;
// vector 示例
vector<int> nums = {3, 1, 4, 1, 5};
sort(nums.begin(), nums.end()); // 排序后: 1,1,3,4,5
// map 示例
map<string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
for (auto& pair : ages) {
cout << pair.first << ": " << pair.second << endl;
}
内存管理(new/delete)
int* p = new int(42); // 动态分配一个整数
cout << *p << endl; // 输出 42
delete p; // 释放内存
// 数组版本
int* arr = new int[10];
for (int i = 0; i < 10; ++i) arr[i] = i * i;
delete[] arr; // 注意使用 delete[]
⚠️ 现代 C++ 推荐使用智能指针(如
unique_ptr,shared_ptr)避免手动管理内存。
3. 实战案例
案例一:数组排序(快速排序)
#include <iostream>
using namespace std;
void quickSort(int arr[], int low, int high) {
if (low >= high) return;
int pivot = arr[(low + high) / 2];
int left = low, right = high;
while (left <= right) {
while (arr[left] < pivot) left++;
while (arr[right] > pivot) right--;
if (left <= right) {
swap(arr[left], arr[right]);
left++;
right--;
}
}
quickSort(arr, low, right);
quickSort(arr, left, high);
}
int main() {
int data[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(data)/sizeof(data[0]);
quickSort(data, 0, n - 1);
for (int i = 0; i < n; ++i)
cout << data[i] << " ";
return 0;
}
案例二:猜数字小游戏
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
int secret = rand() % 100 + 1;
int guess;
cout << "Guess the number (1-100): ";
while (cin >> guess) {
if (guess == secret) {
cout << "Congratulations! You guessed it!\n";
break;
} else if (guess < secret) {
cout << "Too low! Try again: ";
} else {
cout << "Too high! Try again: ";
}
}
return 0;
}
在现代 C++(尤其是 C++11 及以后标准)中,推荐使用智能指针来自动管理动态内存,避免手动调用 new 和 delete 导致的内存泄漏、重复释放或异常安全问题。最常用的智能指针是 std::unique_ptr 和 std::shared_ptr。
1. std::unique_ptr:独占所有权
- 一个对象只能被一个
unique_ptr拥有。 - 不可复制,但可移动(move semantics)。
- 当
unique_ptr离开作用域时,自动释放其所指向的对象。
示例:
#include <iostream>
#include <memory> // 必须包含头文件
class MyClass {
public:
MyClass() { std::cout << "MyClass constructed\n"; }
~MyClass() { std::cout << "MyClass destructed\n"; }
void sayHello() { std::cout << "Hello from MyClass!\n"; }
};
int main() {
// 创建 unique_ptr
std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
ptr->sayHello(); // 使用 -> 调用成员函数
// 自动析构:当 main 结束时,ptr 被销毁,对象自动删除
return 0;
}
✅ 输出:
MyClass constructed
Hello from MyClass!
MyClass destructed
移动语义示例:
auto ptr1 = std::make_unique<MyClass>();
// auto ptr2 = ptr1; // 错误!不能复制
auto ptr2 = std::move(ptr1); // 正确:转移所有权
// 此时 ptr1 为空,ptr2 拥有对象
2. std::shared_ptr:共享所有权
- 多个
shared_ptr可以共享同一个对象。 - 使用引用计数机制:每当增加一个
shared_ptr,计数 +1;减少则 -1。 - 当引用计数为 0 时,对象自动销毁。
示例:
#include <iostream>
#include <memory>
int main() {
// 创建 shared_ptr
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> ptr2 = ptr1; // 共享所有权
std::cout << "Reference count: " << ptr1.use_count() << "\n"; // 输出 2
} // ptr2 离开作用域,计数减为 1
std::cout << "Reference count: " << ptr1.use_count() << "\n"; // 输出 1
return 0; // 此时 ptr1 析构,计数变为0,对象被删除
}
✅ 输出:
MyClass constructed
Reference count: 2
Reference count: 1
MyClass destructed
3. 如何创建智能指针?
| 推荐方式 | 说明 |
|---|---|
std::make_unique<T>() |
C++14 起支持,安全创建 unique_ptr |
std::make_shared<T>() |
高效创建 shared_ptr,建议优先使用 |
⚠️ 不要这样写:
// ❌ 危险:可能造成内存泄漏(异常中断)
std::function<void()> f(new MyClass(), [](MyClass* p){ delete p; });
// 如果 new MyClass() 成功,但在构造函数后抛出异常,资源将未被管理
✅ 应该使用 make_unique / make_shared 来避免此类问题。
4. 实际应用场景对比
| 场景 | 推荐智能指针 |
|---|---|
| 工厂模式返回对象 | std::unique_ptr<Base> |
| 树节点中的父/子关系(避免循环引用) | 子用 std::weak_ptr,父用 std::shared_ptr |
| 多个对象共享同一资源(如缓存) | std::shared_ptr |
| 临时动态对象(如局部对象) | std::unique_ptr |
5. 注意事项
- 避免
shared_ptr循环引用(例如 A 指向 B,B 又指向 A),会导致内存无法释放。 - 使用
std::weak_ptr解决循环引用问题。 - 尽量避免从原始指针构造智能指针(容易出错)。
示例:循环引用问题与 weak_ptr 解法
struct Node;
using NodePtr = std::shared_ptr<Node>;
using WeakNode = std::weak_ptr<Node>;
struct Node {
int id;
WeakNode parent; // 使用 weak_ptr 避免循环引用
Node(int i) : id(i) { std::cout << "Node " << id << " created\n"; }
~Node() { std::cout << "Node " << id << " destroyed\n"; }
};
RAII(Resource Acquisition Is Initialization,资源获取即初始化)是 C++ 中一种重要的编程范式,其核心思想是:
将资源的生命周期绑定到对象的生命周期上 —— 资源在对象构造时获取,在对象析构时自动释放。
这里的“资源”不仅指内存,还包括文件句柄、网络连接、互斥锁、数据库连接等任何需要申请和释放的系统资源。
RAII 的基本原理
- 构造函数中获取资源(如 new 内存、open 文件)
- 析构函数中释放资源(如 delete、close)
- 利用 C++ 的确定性析构机制(对象离开作用域时必定调用析构函数),确保资源不会泄漏。
示例:RAII 管理文件
#include <fstream>
#include <iostream>
class FileHandler {
std::ofstream file;
public:
FileHandler(const std::string& filename) {
file.open(filename);
if (!file.is_open()) {
throw std::runtime_error("Cannot open file!");
}
std::cout << "File opened: " << filename << "\n";
}
void write(const std::string& data) {
file << data << std::endl;
}
~FileHandler() {
if (file.is_open()) {
file.close();
std::cout << "File closed.\n";
}
}
};
int main() {
try {
FileHandler fh("output.txt");
fh.write("Hello, RAII!");
// 离开作用域时自动关闭文件,无需手动调用 close()
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
即使中间发生异常,C++ 的栈展开机制也会调用局部对象的析构函数,从而保证资源被正确释放。
智能指针是 RAII 的典型实现
std::unique_ptr 和 std::shared_ptr 就是基于 RAII 原则设计的经典工具:
| 特性 | 如何体现 RAII |
|---|---|
| 构造时分配内存 | 在 make_unique 或 new 时获取堆内存 |
| 析构时释放内存 | 离开作用域时自动调用 delete 或 delete[] |
| 异常安全 | 即使抛出异常,栈上智能指针仍会析构,防止内存泄漏 |
示例对比:原始指针 vs RAII(智能指针)
❌ 手动管理容易出错:
void bad_example() {
MyClass* ptr = new MyClass();
do_something(); // 如果这里抛出异常
delete ptr; // 这行不会执行 → 内存泄漏!
}
✅ 使用 RAII 自动管理:
void good_example() {
auto ptr = std::make_unique<MyClass>();
do_something(); // 即使抛出异常,ptr 析构时自动释放内存
} // 自动 delete
RAII 的优势
- ✅ 异常安全:无论是否发生异常,资源都能被释放。
- ✅ 代码简洁:无需在多处写
delete或close()。 - ✅ 避免资源泄漏:只要对象是局部变量或成员变量,就能保证析构。
- ✅ 通用性强:可用于内存、锁、socket、GUI 句柄等所有资源。
其他 RAII 应用示例
1. 锁管理(std::lock_guard)
std::mutex mtx;
void thread_safe_func() {
std::lock_guard<std::mutex> lock(mtx); // 构造时加锁
// 操作共享数据
// 析构时自动解锁,即使发生异常也安全
}
2. 自定义资源管理类
比如数据库连接、图形上下文等都可以封装成 RAII 类型。

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)