C++智能指针循环引用破解
智能指针在管理动态内存时可能遇到循环引用问题,导致内存泄漏。weak_ptr是打破循环引用的关键工具,它不增加引用计数。
循环引用发生在两个对象互相持有shared_ptr。
#include
#include
#include
#include
struct LeakyNode {
std::string name;
std::shared_ptr next;
explicit LeakyNode(const std::string& n) : name(n) {
std::cout << "LeakyNode " << name << " created\n";
}
~LeakyNode() {
std::cout << "LeakyNode " << name << " destroyed\n";
}
};
void circular_reference_problem() {
auto a = std::make_shared("A");
auto b = std::make_shared("B");
a->next = b;
b->next = a;
std::cout << "Reference counts:\n";
std::cout << "a use_count: " << a.use_count() << "\n";
std::cout << "b use_count: " << b.use_count() << "\n";
}
shared_ptr循环引用导致内存泄漏。
struct Node {
std::string name;
std::shared_ptr next;
std::weak_ptr prev;
explicit Node(const std::string& n) : name(n) {
std::cout << "Node " << name << " created\n";
}
~Node() {
std::cout << "Node " << name << " destroyed\n";
}
};
void weak_ptr_break_cycle() {
auto a = std::make_shared("A");
auto b = std::make_shared("B");
a->next = b;
b->prev = a;
std::cout << "a use_count: " << a.use_count() << "\n";
std::cout << "b use_count: " << b.use_count() << "\n";
if (auto locked = b->prev.lock()) {
std::cout << "b's prev: " << locked->name << "\n";
}
}
weak_ptr的lock方法获取临时shared_ptr。
void weak_ptr_methods() {
auto shared = std::make_shared(42);
std::weak_ptr weak(shared);
if (auto locked = weak.lock()) {
std::cout << "Locked value: " << *locked << "\n";
std::cout << "Expired: " << weak.expired() << "\n";
}
shared.reset();
if (weak.expired()) {
std::cout << "weak_ptr expired\n";
}
}
二叉树使用weak_ptr避免循环。
struct TreeNode {
int value;
std::shared_ptr left;
std::shared_ptr right;
std::weak_ptr parent;
explicit TreeNode(int v) : value(v) {
std::cout << "TreeNode " << value << " created\n";
}
~TreeNode() {
std::cout << "TreeNode " << value << " destroyed\n";
}
std::shared_ptr get_parent() const {
return parent.lock();
}
};
void tree_example() {
auto root = std::make_shared(1);
auto left = std::make_shared(2);
auto right = std::make_shared(3);
root->left = left;
root->right = right;
left->parent = root;
right->parent = root;
if (auto p = left->get_parent()) {
std::cout << "Parent of left child: " << p->value << "\n";
}
}
enable_shared_from_this解决this获取shared_ptr的问题。
class AsyncOp : public std::enable_shared_from_this {
int id_;
public:
explicit AsyncOp(int id) : id_(id) {}
std::shared_ptr get_shared() {
return shared_from_this();
}
void start() {
auto self = shared_from_this();
std::thread([self]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "AsyncOp " << self->id_ << " completed\n";
}).detach();
}
int id() const { return id_; }
};
void enable_shared_example() {
auto op = std::make_shared(42);
op->start();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
weak_ptr在缓存系统中的应用。
template
class Cache {
std::map> cache_;
std::mutex mtx_;
public:
std::shared_ptr get(const K& key) {
std::lock_guard lock(mtx_);
auto it = cache_.find(key);
if (it != cache_.end()) {
if (auto ptr = it->second.lock()) {
std::cout << "Cache hit for " << key << "\n";
return ptr;
}
}
return nullptr;
}
void insert(const K& key, std::shared_ptr value) {
std::lock_guard lock(mtx_);
cache_[key] = value;
}
size_t size() const {
std::lock_guard lock(mtx_);
return cache_.size();
}
};
void cache_demo() {
Cache cache;
auto s = std::make_shared("cached_value");
cache.insert(1, s);
auto result = cache.get(1);
if (result) {
std::cout << "Got: " << *result << "\n";
}
s.reset();
result = cache.get(1);
if (!result) {
std::cout << "Expired entry removed\n";
}
}
weak_ptr不干扰引用计数,不阻止对象销毁。
void weak_ptr_lifecycle() {
std::weak_ptr weak;
{
auto shared = std::make_shared(100);
weak = shared;
std::cout << "Inside scope, expired: " << weak.expired() << "\n";
}
std::cout << "Outside scope, expired: " << weak.expired() << "\n";
}
使用weak_ptr正确管理对象生命周期,避免循环引用导致的内存泄漏。
C++智能指针循环引用破解
张小明
前端开发工程师
Obsidian Outliner拖拽功能实战技巧:深度解析列表结构可视化重构
Obsidian Outliner拖拽功能实战技巧:深度解析列表结构可视化重构 【免费下载链接】obsidian-outliner Work with your lists like in Workflowy or RoamResearch 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-outliner Obsidian Outliner作为Obsid…
DISC性格色彩:从理论到实战,打造高效沟通与协作的底层逻辑
1. DISC性格色彩理论的核心框架 DISC理论将人的行为风格划分为四种基本类型:支配型(D)、影响型(I)、稳健型(S)和谨慎型(C)。这套体系最早由美国心理学家威廉莫尔顿马斯顿在20世纪20年代提出,最初用于研究普通人群的情绪反应模式。经过近百年的发展&#…
近协议网关深度解析:从二进制流到统一MQTT消息的工程实践
近协议网关深度解析:从二进制流到统一MQTT消息的工程实践 1. 概述:什么是近协议网关 “近协议网关”是指在物联网接入层中,位于车辆终端与云端消息中间件之间的轻量级协议转换组件。它负责将终端侧的原生二进制协议(如JT/T 808、GB/T 32960)透明地转换为基于MQTT主题发布…
3分钟生成专业短视频:终极免费AI视频生成神器MoneyPrinterTurbo
3分钟生成专业短视频:终极免费AI视频生成神器MoneyPrinterTurbo 【免费下载链接】MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频 Generate short videos with one click using AI LLM. 项目地址: https://gitcode.com/GitHub_Trending/mo/MoneyP…
Trae:字节跳动推出的 AI 原生 IDE
一、什么是 Trae?Trae 是字节跳动推出的一款 AI 原生集成开发环境(IDE),定位与 Cursor 类似,但更加注重:中文开发场景AI Agent 自动开发多模型协同企业级应用开发它并不是简单地给 VS Code 加一个聊天框&am…
OpCore Simplify:革命性的黑苹果自动化配置工具
OpCore Simplify:革命性的黑苹果自动化配置工具 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在普通PC上安装macOS一直是技术爱好者面临…