c++ 智能指针std::shared_ptr
c++11中常用的智能指针有shared_ptr
,unique_ptr
与weak_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指针,保证了安全性。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探