Day 3 学习计划:智能指针与资源管理(C++11 重点)
·
DAY3
✅ Day 3 学习计划:智能指针与资源管理(C++11 重点)
🎯 今日目标:
- 理解
unique_ptr/shared_ptr/weak_ptr的使用和区别 - 掌握智能指针的底层机制(引用计数、所有权)
- 理解资源泄漏问题与解
- 理解循环引用及其危害与解除方案
📘 一、系统知识学习
1. 什么是智能指针?
- 智能指针是一种类模板,用来自动管理内存(RAII 原则实现)
- 避免手动
delete,防止内存泄漏
2. unique_ptr
- 独占式智能指针,不可复制,只能移动
- 常用接口:
std::make_unique<T>() - 应用场景:管理不共享的资源
std::unique_ptr<int> p1 = std::make_unique<int>(10);
// std::unique_ptr<int> p2 = p1; // 编译错误
std::unique_ptr<int> p2 = std::move(p1); // 转移所有权
3. shared_ptr
- 引用计数式共享智能指针
- 多个
shared_ptr指向同一块内存,最后一个析构时释放 - 常用接口:
std::make_shared<T>()
4. weak_ptr
- 弱引用,不增加引用计数
- 用于解决
shared_ptr之间的 循环引用问题 - 可通过
lock()获取临时有效的shared_ptr
5. 智能指针底层机制
shared_ptr内部包含引用计数控制块(use_count / weak_count)use_count()显示当前引用次数- 线程安全的引用计数实现(原子操作)
6. 循环引用的问题
struct A;
struct B;
struct A {
std::shared_ptr<B> bptr;
};
struct B {
std::shared_ptr<A> aptr; // 💥 循环引用,内存泄漏
};
// 正解:B 使用 weak_ptr
struct B2 {
std::weak_ptr<A> aptr; // ✅ 不增加引用计数
};
💻 二、实践任务:智能指针示例代码
建议任务:
- 手写一个
shared_ptr的引用计数模拟类 - 用
unique_ptr管理一个动态数组资源 - 用
shared_ptr+weak_ptr解决 A ↔ B 互持问题
❓ 三、面试题巩固
推荐今日 C++ 面试题:
shared_ptr的引用计数原理?shared_ptr和unique_ptr有哪些区别?- 如何避免
shared_ptr产生的循环引用?make_shared()为什么比直接 new 更推荐?
🎯 四、设计模式学习任务:观察者模式(Observer)
场景:
- 一对多依赖关系,一处变化通知多处
- 典型:事件订阅 / 消息通知机制
#include <vector>
#include <iostream>
#include <memory>
#include <algorithm>
#include <mutex>
// 1. 抽象观察者接口
class Observer {
public:
virtual ~Observer() = default;
virtual void update(int value) = 0; // 更新接口
};
// 2. 具体观察者实现
class Logger : public Observer {
public:
void update(int value) override {
std::cout << "[Logger] Value changed to: " << value << std::endl;
}
};
class AlertSystem : public Observer {
const int threshold_ = 100;
public:
void update(int value) override {
if (value > threshold_) {
std::cout << "⚠️ [ALERT] Value exceeded threshold: " << value
<< " > " << threshold_ << std::endl;
}
}
};
class GraphUpdater : public Observer {
public:
void update(int value) override {
std::cout << "📈 [Graph] Rendering new value: ";
for (int i = 0; i < value % 10; ++i) std::cout << "■";
std::cout << std::endl;
}
};
// 3. 主题(被观察者)完整实现
class Subject {
std::vector<Observer*> observers_; // 观察者列表
std::mutex mtx_; // 线程安全锁
public:
virtual ~Subject() = default;
// 添加观察者 (支持多态)
void attach(Observer* obs) {
std::lock_guard<std::mutex> lock(mtx_);
observers_.push_back(obs);
}
// 移除观察者
void detach(Observer* obs) {
std::lock_guard<std::mutex> lock(mtx_);
observers_.erase(
std::remove(observers_.begin(), observers_.end(), obs),
observers_.end()
);
}
// 通知所有观察者 (推模型)
void notify(int value) {
std::lock_guard<std::mutex> lock(mtx_);
for (auto obs : observers_) {
obs->update(value); // 多态调用
}
}
// 提供拉模型接口(可选)
virtual int getState() const = 0;
};
// 4. 具体主题实现 - 温度传感器
class TemperatureSensor : public Subject {
int temperature_ = 0;
public:
void setTemperature(int temp) {
if (temp != temperature_) {
temperature_ = temp;
notify(temp); // 状态变化时通知观察者
}
}
int getState() const override {
return temperature_;
}
};
// 5. 智能指针管理扩展(避免悬挂指针)
class SafeSubject : public Subject {
std::vector<std::weak_ptr<Observer>> weak_observers_;
std::mutex mtx_;
public:
void attach(std::shared_ptr<Observer> obs) {
std::lock_guard<std::mutex> lock(mtx_);
weak_observers_.push_back(obs);
}
void notify(int value) override {
std::lock_guard<std::mutex> lock(mtx_);
auto it = weak_observers_.begin();
while (it != weak_observers_.end()) {
if (auto shared_obs = it->lock()) {
shared_obs->update(value);
++it;
} else {
it = weak_observers_.erase(it); // 自动清除失效观察者
}
}
}
};
// 6. 使用示例
int main() {
// 创建主题(被观察者)
TemperatureSensor sensor;
// 创建观察者
Logger logger;
AlertSystem alert;
GraphUpdater graph;
// 注册观察者
sensor.attach(&logger);
sensor.attach(&alert);
sensor.attach(&graph);
// 模拟数据变化
sensor.setTemperature(25); // 正常更新
sensor.setTemperature(120); // 触发警报
sensor.setTemperature(8); // 图形更新
// 移除观察者示例
sensor.detach(&graph);
std::cout << "\n--- Detached GraphUpdater ---\n";
sensor.setTemperature(30); // 不再显示图形
// 智能指针版本示例
SafeSubject safe_sensor;
auto safe_logger = std::make_shared<Logger>();
safe_sensor.attach(safe_logger);
{
auto temp_alert = std::make_shared<AlertSystem>();
safe_sensor.attach(temp_alert);
safe_sensor.notify(150); // 两个观察者都生效
} // temp_alert 离开作用域,自动解除注册
std::cout << "\n--- AlertSystem destroyed ---\n";
safe_sensor.notify(50); // 仅logger生效(自动清理失效观察者)
}
- 可升级为使用
std::function+ 回调注册的现代写法
🔢 五、LeetCode 算法题推荐(指针+链表方向)
- LeetCode 141. 环形链表(快慢指针)
- LeetCode 160. 相交链表(长度差 + 双指针)
📝 六、今日总结
shared_ptr和unique_ptr的使用总结weak_ptr的使用场景代码- 面试题答案归纳
- LeetCode 题解与思路
- 观察者模式的结构图 + 代码实现(可类比 Qt 的信号槽机制)
更多推荐

所有评论(0)