Smart_ptr库

本文详细介绍了Boost库中的智能指针,包括scoped_ptr、shared_ptr、intrusive_ptr、weak_ptr及其作用,以及如何在不同场景下选择合适的智能指针进行资源管理。

    除了标准库提供的智能指针std::auto_ptr外,boost中存在六个智能指针:scoped_ptr,shared_ptr,intrusive_ptr,weak_ptr和scoped_array,shared_array。

   相比于std::auto_ptr不能用作STL容器的元素,Boost的智能指针则填补了这个空白。


--何时需要智能指针

a).资源的共享所有权中:两个或多个对象必须同时使用第三个对象的情况。

b).编写异常安全的代码时:在异常抛出时没有资源泄漏,并保证程序状态的一致性。

c).避免常见错误,例如资源泄漏时:比如忘记调用delete函数,或没有正确调用delete[]等。


--智能指针scoped_ptr:

a).头文件:#include <boost/scoped_ptr.hpp>
b).说明:

拥有类似于std::auto_ptr的特征,但不同在于不会像std::auto_ptr那样转移所有权。

拥有所指向资源的所有权,并且永远不会意外地放弃所有权。

c).提纲:
namespace boost{
template<typename T>
class scoped_ptr:noncopyable
{
public:
explicit scoped_ptr(T * p=0);
~scoped_ptr();
void reset(T * p=0);//先delete掉原资源,在关联新资源
T& operator*() const;//这两个操作是scoped_ptr能够像裸指针一样使用
T* operator->() const;//这两个操作是scoped_ptr能够像裸指针一样使用
T* get() const;//可以用于判断是否绑定的是空指针,不过常用方法是直接使用if(p)想过等同于if(p.get())。
void swap(scoped_ptr & b);
};//class scoped_ptr
template<typename T>
void swap(scoped_ptr<T> & a,scoped_ptr<T> & b);

}	//namespace boost

d).小结:scoped_ptr给我的感觉主要有两个功能:

利用析构函数自动调用delete函数;

利用scoped_ptr的生命期来管理所指向资源的生命期--即在socped_ptr对象生命期结束是自动调用析构函数。

--智能指针scoped_array

a).小结:

头文件:#include <boost/scoped_array.hpp>

其与scoped_ptr的关系相当于new和new[]的关系,用于管理动态数组,在析构函数中调用delete[]函数。

推荐使用std::vector。


--智能指针shared_ptr:

a).头文件:#include <boost/shared_ptr.hpp>
b).说明:

适用的情况是多个对象共享一个指针的时候,就不用管理什么时候delete指针了。

关键点在名字中的shared,通过在内部使用一个计数器来实现多个对象共享一个指针。

c).提纲:
namesapce boost{

template<typename T>

class shared_ptr{

public:

template<class Y>

explicit shared_ptr(Y * p);

template<class Y,class D>

shared_ptr(Y * p,D d);

~shared_ptr();

shared_ptr(const shared_ptr & r);

template<class Y>

explicit shared_ptr(const weak_ptr<Y> & r);

template<class Y>

explicti shared_ptr(std::auto_ptr<Y> & r);

shared_ptr& operator=(const shared_ptr & r);

void reset(); //停止对指针的共享,应用计数将减一

T& operator*() const;

T* operator->() const;

T* get() const;

bool unique() const; //判断是否是指针的唯一拥有者

long use_count() const; //返回引用计数器的值

operator unspecified-bool-type() const;

void swap(shared_ptr<T> & b);

};

template<class T,class U>

shared_ptr<T> static_pointer_cast(const shared_ptr<U> & r); //引用计数安全的转换
} //namespace boost

d).小结:

使用情况的理解是所有指针都使用智能指针,因为如果有直接使用裸指针的情况下智能指针还是不能记录的。

内部原理猜测:

应该是在初次使用的时候建立一个共享计数器,

以后没增加一个智能指针来引用就把指针和共享计数器一起拷贝过去,

智能指针的接口能根据情况调用计数器--因为计数器是共享的所以所有持有计数器的智能指针都接收到最新消息。

计数器应该是线程安全的,但递减为零时就调用delete函数。

shared_ptr还可以提供删除工具而不掉用delete函数。


--enable_shared_from_this:

头文件:#include <boost/enable_shared_from_this.hpp>

小结:

使用情况是需要将this转化为shared_ptr的时候。

使用方法:

通过继承enbale_shared_from_this<被继承的类类型>就可以使用方法shared_from_this()来获得this的shared_ptr。


--shared_array:

头文件:#include <boost/shred_array.hpp>

小结:

主要是对指针数组的智能指针,不过推荐使用std::vector。


--intrusive_ptr:

头文件:#include <boost/intrusive_ptr.hpp>

小结:

这个智能指针是对shared_ptr的扩展,shared_ptr是内部维护引用计数器(非侵入式)的,intrusive_ptr是侵入式的--即自己提供引用计数器的管理。

自己提供引用计数器主要是提供两个需要增减引用计数器时给intrusive_ptr调用的特定的函数。

关于这两个函数也有一定的技巧。


--weak_ptr:

头文件:#inlcude <boost/weak_ptr.hpp>

小结:

weak_ptr对于shared_ptr来说是一个重要的伙伴。

需要weak_ptr的情况:需要打破循环依赖;需要使用共享资源而不是共享所有权;避免悬空指针。


总结:

个人感觉智能库的核心还是shared_ptr,不过每一个都适用不同的情况,但shared_ptr使用更广泛一些。

而且智能指针也可以作为一种内存管理的方法和学习的好的例子。

<think>嗯,我现在需要解决用户关于boost shared_ptr在指定行出现断言失败的问题。首先,用户提供了几个引用信息,其中引用[5]明确指出错误原因是智能指针未初始化,并给出了示例代码。用户的需求是查找代码中`boost/include/boost/smart_ptr/shared_ptr.hpp:734`处的`Assertion 'px != 0' failed`错误的解决方案。 首先,我需要理解这个断言错误的含义。根据boost的源码,当调用`operator->`或`operator*`时,会检查内部的指针`px`是否为空。如果`px`为0(即nullptr),就会触发这个断言失败。因此,核心问题是使用了未初始化或已释放的`shared_ptr`。 接下来,结合用户提供的引用,特别是引用[5]中的例子,可以看到错误是因为声明了`viewer1`智能指针但未初始化,直接使用导致错误。正确的做法是初始化时分配对象。因此,解决方案的第一步就是检查所有相关智能指针的初始化情况。 然后,我需要列举可能的触发场景。除了未初始化,还有可能是智能指针被重置为null或指向的对象已被释放。例如,在作用域结束时智能指针自动释放对象,后续再使用该指针就会出错。另外,多线程环境下竞争条件也可能导致问题,但相对少见。 用户的问题中提到了具体的文件路径和行号,但实际错误可能发生在代码的任何地方,关键在于找到哪个指针未初始化就被使用。因此,调试时需要检查堆栈回溯,找到引发错误的调用位置。 解决问题的方法包括:使用调试器(如gdb)捕获core文件,检查调用栈;在代码中添加日志或断言,确保指针在使用前非空;审查所有相关智能指针的生命周期管理,确保正确初始化和所有权管理。同时,注意循环引用可能导致内存无法释放,但这里的问题更可能是空指针而非悬垂指针。 最后,用户可能需要具体的步骤指导,比如如何用gdb调试,或者代码审查的重点。此外,建议用户检查第三方的使用,如引用中提到的PCL,确保其兼容性或正确初始化。总结解决方案的核心就是保证使用智能指针前其内部指针不为空。 </think>针对 `boost::shared_ptr` 在 `shared_ptr.hpp:734` 处触发 `Assertion 'px != 0' failed` 错误,以下是根本原因分析和解决方案: ### 错误原因 1. **未初始化智能指针**(最常见) 声明了 `shared_ptr` 对象但未分配有效内存,直接调用成员访问操作符 `->` 或解引用操作符 `*`。 ```cpp boost::shared_ptr<MyClass> ptr; // 未初始化,px = nullptr ptr->method(); // 触发断言崩溃 ``` 2. **意外重置指针** 通过 `reset()` 或赋值将指针置空后错误使用: ```cpp ptr.reset(); // px = nullptr ptr->access(); // 触发断言 ``` 3. **对象提前析构** 其他 `shared_ptr` 实例提前释放对象,导致当前指针悬空: ```cpp auto ptr1 = boost::make_shared<MyClass>(); auto ptr2 = ptr1; ptr1.reset(); // 对象未被释放(ptr2仍持有) ptr2.reset(); // 对象实际析构 if(ptr2) ptr2->use(); // 错误:ptr2非空但px=nullptr ``` 4. **多线程竞争** 未加锁的情况下多线程同时修改 `shared_ptr`(较少见)。 --- ### 解决方案 #### 1. **初始化所有智能指针** ```cpp // 错误声明 boost::shared_ptr<MyClass> ptr; // 正确初始化(任选其一) auto ptr = boost::make_shared<MyClass>(); // 推荐 boost::shared_ptr<MyClass> ptr(new MyClass); // 显式构造 ``` #### 2. **使用前检查有效性** ```cpp if(ptr && ptr.unique()) { // 检查非空且独占所有权 ptr->safe_call(); } ``` #### 3. **调试与排查技巧** - **启用Core Dump分析** 通过GDB回溯崩溃点: ```bash gdb ./your_program core (gdb) backtrace ``` - **添加断言检查** 在关键位置插入验证: ```cpp BOOST_ASSERT_MSG(ptr, "Smart pointer is null at function X"); ``` - **日志追踪** 记录 `shared_ptr` 的构造/析构: ```cpp MyClass() { std::cout << "构造@" << this << std::endl; } ~MyClass() { std::cout << "析构@" << this << std::endl; } ``` #### 4. 第三方集成注意事项 当使用PCL等时(如引用[2][4][5]): - **检查工厂函数返回值**:PCL的 `createXxx()` 可能返回空指针 - **验证初始化流程**: ```cpp pcl::Visualizer::Ptr viewer = pcl::createVisualizer("Viewer"); // 确认createVisualizer未返回空 ``` --- ### 关键总结 | **错误类型** | **触发场景示例** | **修复方案** | |-------------------|-------------------------------|----------------------------| | 未初始化指针 | `shared_ptr<T> ptr; ptr->foo()` | 必须显式初始化 | | 空指针解引用 | `ptr.reset(); ptr->bar()` | 使用前添加 `if(ptr)` 检查 | | 对象提前释放 | 多实例竞争释放 | 用 `weak_ptr` 替代跨模块传递 | > 💡 **经验提示**:该断言明确指向 `px == nullptr`(即智能指针内部原始指针为空)。优先检查指针初始化状态和生命周期管理逻辑 [^5][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值