c++ 智能指针std::shared_ptr

c++11中常用的智能指针有shared_ptrunique_ptrweak_ptr。

unique_ptr是独占型指针,其计数永远为1,无拷贝构造函数,但可以使用std::move转移资源所有权。

weak_ptr没有资源所有权,一般用来辅助shared_ptr使用,多使用于多线程,循环等场景。

shared_ptr可以多个指针绑定同一对象,同一堆空间每多一个shared_ptr指向该空间,计数就+1。计数为0时析构。

可以使用get()方法获得智能指针的原始指针。

可以使用reset()方法改变智能指针的指向,并使其原本的计数-1。

智能指针在声明时可以显示指明第二个参数即删除器(deleter)。删除器是一个可调用对象(函数、函数对象或Lambda表达式),用于在 智能指针 被销毁时执行特定的操作。

std::unique_ptr<FILE, decltype(&fclose)> file(fopen("data.txt", "r"), &fclose);
auto widgetDeleter = [](Widget* pw) { … };
std::shared_ptr<Widget> spw(new Widget, widgetDeleter);

上例中对file绑定了删除函数fclose,确保在file被销毁时,关闭文件的操作被正确执行。需要注意的是,删除器的类型必须与所管理对象的指针类型兼容。

需注意,shared_ptr和unique_ptr的删除器绑定方法不同,unique_ptr若绑定删除器需改变其自身类型,而shared_ptr删除器绑定仅是第二个可选参数。

需注意,使用shared_ptr时,应避免用裸指针去初始化shared_ptr,因为同一裸指针初始化多个shared_ptr会导致该多个shared_ptr的计数器均为1(即各个shared_ptr的分组不同),会导致重复析构。

可以使用make_shared或直接用new的右值去初始化shared_ptr。

atuo p=new A();
std::shared_ptr<A> sp1(p);     //避免使用
std::shared_ptr<A> sp2(p);     //不同分组!
std::shared_ptr<A> sp3(sp1.get());    //不同分组!
//以下为常用初始化方法
std::shared_ptr<A> sp1(new A());
std::shared_ptr<A> sp1 = make_shared<A>();

当遇到需要在类中返回一个当前对象的shared_ptr,不能直接retrun shared_ptr(this),因为这种方法同样也是类似裸指针初始化,会导致重复析构。

可以将有该需求的类变成std::enable_shared_from_this模板对象的派生类,从而可以使用shared_from_this()方法安全的返回一个shared_ptr。

复制代码
class A : public std::enable_shared_from_this<A>
{
public:
    A()
    {
        std::cout << "A constructor" << std::endl;
    }
​
    ~A()
    {
        std::cout << "A destructor" << std::endl;
    }
​
    shared_ptr<Object> func(int key){
        shared_ptr<Object> shObject;
        shObject.reset(new Object(key), boost::bind(& A::cbDelete,shared_from_this(), _1));    //此处使用shared_from_this()
        return shObject;
    }
private:
    void cbDelete(Object* obj){
        ....
        delete obj;
    }
};
复制代码

观察上例可看到在func函数中,需要将shObject用reset将其指向new得到的Object对象,同时给了reset函数的第二个参数,绑定了删除器。而该绑定需要本对象的this指针,此处使用了shared_from_this()函数而非直接传递this指针,保证了安全性。

 

posted @   _Explosion!  阅读(95)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示