weak_ptr基本用法

正确的做法

weak_ptr主要是配合share_ptr来实现应用计数,同时不会发生循环引用。

参考:http://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html

#include "boost/smart_ptr.hpp"
#include "boost/weak_ptr.hpp"

#include<iostream>
using namespace std;
using namespace boost;

class node;
typedef boost::weak_ptr<node> ptr_type;

class node
{
public:
	node();	
	~node();
	int value_;
	ptr_type next;
};

node::node()
{
	cout<<"node()"<<endl;
}

node::~node()
{
	cout<<"~node()"<<endl;
}

int main(int,char**)
{
	auto p1 = boost::make_shared<node>();
	auto p2 = boost::make_shared<node>();
	p1->next = p2;//weak_ptr(const share_ptr&) //不增加引用计数
	p2->next = p1;//weak_ptr(const share_ptr&) //不增加引用计数

	return 0;
};

程序输出:

node()
node()
~node()
~node()
请按任意键继续. . .
导致循环引用的情形
#include "boost/smart_ptr.hpp"
#include "boost/weak_ptr.hpp"

#include<iostream>
using namespace std;
using namespace boost;

class node;
//typedef boost::weak_ptr<node> ptr_type;
typedef boost::shared_ptr<node> ptr_type;//这样会发生循环引用

class node
{
public:
	node();	
	~node();
	int value_;
	ptr_type next;//是否会循环引用取决于ptr_type的类型
};

node::node()
{
	cout<<"node()"<<endl;
}

node::~node()
{
	cout<<"~node()"<<endl;
}

int main(int,char**)
{
	auto p1 = boost::make_shared<node>();
	auto p2 = boost::make_shared<node>();
	p1->next = p2;//weak_ptr(const share_ptr&) //不增加引用计数
	p2->next = p1;//weak_ptr(const share_ptr&) //不增加引用计数

	return 0;
};
程序输出(只有创建对象,没有释放对象):
node()
node()
请按任意键继续. . .






<think>好的,用户现在想了解C++中的std::weak_ptr和shared_ptr的使用方法。之前他们问过函数重写,现在转向智能指针,可能是在学习内存管理或准备项目。需要先理清两者的基本概念和区别。 首先,用户可能知道shared_ptr是用于共享所有权的智能指针,但weak_ptr的作用可能不太清楚。需要解释weak_ptr如何解决循环引用的问题,以及它的使用场景。 需要明确shared_ptr通过引用计数管理资源,而weak_ptr不增加引用计数,只是观察资源。要举例说明循环引用的情况,比如两个类相互持有shared_ptr,导致内存泄漏,这时候weak_ptr可以打破循环。 然后,具体的使用方法部分,分点说明shared_ptr的创建、所有权共享、注意事项,比如避免裸指针初始化多个shared_ptr。对于weak_ptr,要说明如何通过shared_ptr创建,以及如何通过lock()获取临时shared_ptr来访问资源。 可能用户需要知道如何正确使用weak_ptr,比如检查是否过期,以及何时使用。示例代码会有帮助,比如一个简单的类互相引用,展示如何用weak_ptr解决循环引用。 还要注意提及enable_shared_from_this,当类需要传递自身的shared_ptr时使用,避免用this创建shared_ptr导致的问题。 最后总结两者的使用场景和注意事项,确保用户理解何时使用哪种指针,以及常见错误如何避免。比如shared_ptr用于共享所有权,weak_ptr用于观察但不拥有,避免循环引用导致的内存泄漏。 需要检查是否有遗漏点,比如make_shared的优势,控制块的结构,weak_ptr如何不影响引用计数,以及lock()的使用方法是否正确。确保回答结构清晰,步骤明确,示例易懂,帮助用户逐步理解两者的用法和区别。</think>在C++中,`std::shared_ptr` 和 `std::weak_ptr` 是智能指针的核心组件,用于自动管理动态内存的生命周期。以下是它们的核心用法和区别: --- ### **1. `std::shared_ptr`(共享所有权)** #### **用途** - 多个指针共享同一块内存的所有权。 - 内存的释放由最后一个持有该内存的 `shared_ptr` 负责。 #### **核心方法** ```cpp #include <memory> // 创建方式 auto sp1 = std::make_shared<int>(42); // 推荐:高效且安全 std::shared_ptr<int> sp2(new int(42)); // 直接初始化 std::shared_ptr<int> sp3 = sp1; // 复制构造(引用计数+1) // 使用 *sp1 = 100; // 解引用操作 sp1.reset(); // 手动释放所有权(引用计数-1) if (sp1) { /* 检查是否为空 */ } ``` #### **引用计数机制** - 每个 `shared_ptr` 内部维护一个 **控制块**,记录引用计数和内存地址。 - 当引用计数归零时,自动调用 `delete` 释放内存。 - 示例: ```cpp auto a = std::make_shared<int>(10); // 引用计数=1 auto b = a; // 引用计数=2 b.reset(); // 引用计数=1 a.reset(); // 引用计数=0,内存释放 ``` #### **注意事项** - **避免循环引用**:两个 `shared_ptr` 相互持有会导致内存泄漏(需用 `weak_ptr` 解决)。 - **不要用裸指针初始化多个 `shared_ptr`**:会导致多次释放内存。 ```cpp int* raw_ptr = new int(10); std::shared_ptr<int> p1(raw_ptr); std::shared_ptr<int> p2(raw_ptr); // 错误!会重复释放内存 ``` --- ### **2. `std::weak_ptr`(观察所有权,不持有资源)** #### **用途** - 解决 `shared_ptr` 的循环引用问题。 - 观察 `shared_ptr` 管理的资源,但不增加引用计数。 #### **核心方法** ```cpp // 从 shared_ptr 创建 weak_ptr auto sp = std::make_shared<int>(42); std::weak_ptr<int> wp(sp); // 检查资源是否存在 if (auto locked = wp.lock()) { // 尝试获取 shared_ptr *locked = 100; // 使用资源 } else { // 资源已被释放 } ``` #### **关键特性** - **不控制生命周期**:`weak_ptr` 的创建和销毁不会影响引用计数。 - **必须通过 `lock()` 获取临时 `shared_ptr`** 才能访问资源。 - 示例(解决循环引用): ```cpp class B; class A { public: std::shared_ptr<B> b_ptr; ~A() { std::cout << "A destroyed\n"; } }; class B { public: std::weak_ptr<A> a_weak_ptr; // 使用 weak_ptr 替代 shared_ptr ~B() { std::cout << "B destroyed\n"; } }; int main() { auto a = std::make_shared<A>(); auto b = std::make_shared<B>(); a->b_ptr = b; b->a_weak_ptr = a; // 不会增加 A 的引用计数 // a 和 b 的引用计数最终会归零,内存正确释放 } ``` --- ### **3. 对比总结** | 特性 | `shared_ptr` | `weak_ptr` | |---------------------|-----------------------------------|-----------------------------------| | **所有权** | 共享所有权 | 无所有权,仅观察 | | **引用计数** | 增加引用计数 | 不增加引用计数 | | **资源访问** | 直接通过 `operator*` 或 `->` | 必须通过 `lock()` 获取临时 `shared_ptr` | | **典型场景** | 共享动态资源 | 打破循环引用、缓存、观察者模式 | | **内存释放时机** | 引用计数归零时释放 | 不参与内存释放 | --- ### **4. 最佳实践** 1. **优先使用 `make_shared`**:避免显式 `new`,减少内存碎片和控制块分离。 2. **循环引用必须用 `weak_ptr`**:例如双向关联的类(如树节点、图形关系)。 3. **不要混合使用裸指针和智能指针**: ```cpp auto sp = std::make_shared<int>(10); int* raw = sp.get(); // 仅用于只读场景,切勿用 raw 初始化其他智能指针 ``` 4. **继承 `std::enable_shared_from_this`**:当类需要返回自身的 `shared_ptr` 时。 ```cpp class MyClass : public std::enable_shared_from_this<MyClass> { public: std::shared_ptr<MyClass> get_self() { return shared_from_this(); // 安全获取 this 的 shared_ptr } }; ``` --- ### **示例:缓存系统** ```cpp class Cache { private: std::unordered_map<int, std::weak_ptr<LargeData>> cache; public: std::shared_ptr<LargeData> get(int id) { auto it = cache.find(id); if (it != cache.end()) { auto sp = it->second.lock(); // 尝试获取数据 if (sp) return sp; // 数据仍存在,直接返回 } // 数据不存在或已释放,重新加载 auto data = std::make_shared<LargeData>(load_data(id)); cache[id] = data; // 存储 weak_ptr return data; } }; ``` 通过 `shared_ptr` 和 `weak_ptr` 的配合,可以高效实现资源的安全管理和复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值