在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智能指针 4. weaked_ptr: 到 std::shared_ptr 所管理对象的弱引用 1.1 weak_ptr参考:https://zh.cppreference.com/w/cpp/memory/weak_ptr
循环引用的问题:该被调用的析构函数没有被调用 #include <iostream> #include <memory> using namespace std; class Parent; typedef std::shared_ptr<Parent> ParentPtr; class Child { public: ParentPtr father; Child() { cout << "hello Child" << endl; } ~Child() { cout << "bye Child\n"; } }; typedef std::shared_ptr<Child> ChildPtr; class Parent { public: ChildPtr son; Parent() { cout << "hello parent\n"; } ~Parent() { cout << "bye Parent\n"; } }; void testParentAndChild() { ParentPtr p(new Parent()); ChildPtr c(new Child()); p->son = c; c->father = p; } int main() { testParentAndChild(); return 0; } 问题:c只有调用p的析构的时候,才能被释放。p只有调用c的析构的时候,才能被释放。。形成了循环引用,造成了内存泄露 因此,引入新的智能指针,weak_ptr 1.2 weak_ptr基本用法一旦外部指向shared_ptr资源失效,那么weak_ptr管理的资源自动失效 #include <iostream> #include <cassert> #include <memory> using namespace std; class Object { public: Object(int id) : m_id(id) { std::cout << "init obj " << m_id << std::endl; } ~Object() { std::cout << "bye bye " << m_id << std::endl; } int id() const { return m_id; } private: int m_id; }; void sharedPtrWithWeakPtr() { typedef std::shared_ptr<Object> ObjectPtr; typedef weak_ptr<Object> WeakObjectPtr; ObjectPtr obj(new Object(1)); // 一旦外部指向shared_ptr资源失效,那么weak_ptr管理的资源自动失效 WeakObjectPtr weakObj2; // 裸指针 WeakObjectPtr weakObj(obj); // 指向shared_ptr指针 WeakObjectPtr weakObj3(obj); cout << "obj use count is " << obj.use_count() << endl; // 1--尽管weak_ptr也指向obj,但他只是监听者,本身并不影响引用计数次数 { // weak_ptr使用方法 // 外部至少还有一个shared_ptr来管理资源,同时p自己本身的资源 -- p.use_count >= 2 auto p = weakObj.lock(); // auto == ObjectPtr if (p) { cout << p.unique() << endl; // 0 -- p.use_count() >= 2 } else { } } // 不指向某份资源 // obj.reset(); // { // auto p = weakObj.lock(); // auto == ObjectPtr // if (p) { // assert(false); // } // else { // cout << "null" << endl; // 如果调用reset,就会执行这句话 // } // } // 此时, Object(1)已经失效 obj.reset(new Object(2)) ; { auto p = weakObj.lock(); // 返回值如果有效, 在外部必须有weakObj指向同一个资源 if (p) { assert(false); } else { cout << "null " << endl; // null } } weakObj = obj; // 又有效了 // 想知道weak_ptr有没有管理一份资源(外部有没有资源), 又不想生成一个shared_ptr if (weakObj.expired()) { // 资源过期了 -- true cout << "no ptr" << endl; } else { cout << "have resource\n"; } } int main() { sharedPtrWithWeakPtr(); return 0; } 1.3 解决类之间循环引用一旦外部指向shared_ptr资源失效,那么weak_ptr管理的资源自动失效 #include <iostream> #include <cassert> #include <memory> using namespace std; class Parent; typedef std::shared_ptr<Parent> ParentPtr; typedef std::weak_ptr<Parent> WeakParentPtr; class Child { public: WeakParentPtr father; // 只有一环换成 weak_ptr, 即可打破环 Child() { cout << "hello Child" << endl; } ~Child() { cout << "bye Child\n"; } }; typedef std::shared_ptr<Child> ChildPtr; typedef std::weak_ptr<Child> WeakChildPtr; class Parent { public: ChildPtr son; Parent() { cout << "hello parent\n"; } ~Parent() { cout << "bye Parent\n"; } }; void testParentAndChild() { ParentPtr p(new Parent()); ChildPtr c(new Child()); p->son = c; c->father = p; cout << (c->father).use_count() << endl; cout << (p->son).use_count() << endl; } int main() { testParentAndChild(); return 0; } 析构函数成功调用, 注意析构顺序,谁是weak_ptr对象,就先析构谁。 1.4 用 enable_shared_from_this从this转换到shared_ptr
主要代码: handleChildAndParent(shared_from_this(), ps); 完整代码: #include <iostream> #include <cassert> #include <memory> using namespace std; class Parent; typedef std::shared_ptr<Parent> ParentPtr; typedef std::weak_ptr<Parent> WeakParentPtr; class Child : public std::enable_shared_from_this<Child> // 奇异模板参数 CRTP { public: WeakParentPtr father; // 只有一环换成 weak_ptr, 即可打破环 Child() { cout << "hello Child" << endl; } ~Child() { cout << "bye Child\n"; } void CheckRelation() { } }; typedef std::shared_ptr<Child> ChildPtr; typedef std::weak_ptr<Child> WeakChildPtr; void handleChildAndParent(const ParentPtr& p, const ChildPtr& c); class Parent : public enable_shared_from_this<Parent> { public: WeakChildPtr son; Parent() { cout << "hello parent\n"; } ~Parent() { cout << "bye Parent\n"; } void CheckRelation() { auto ps = son.lock(); if (ps) { //原理: 类中存在weak_ptr指针,通过一系列方式转换成 shared_ptr,然后传参 handleChildAndParent(shared_from_this(), ps); // 使用CRTP来使用 本对象的指针 ★ ★ ★ ★ } cout << "after call checkRelation\n"; } }; void testParentAndChild() { ParentPtr p(new Parent()); ChildPtr c(new Child()); p->son = c; c->father = p; cout << (c->father).use_count() << endl; cout << (p->son).use_count() << endl; p->CheckRelation(); } void handleChildAndParentRef(const Parent& p, const Child& c) { auto cp = c.father.lock(); auto pc = p.son.lock(); if (cp.get() == &p && pc.get() == &c) { cout << "right relation" << endl; } else { cout << "oop !!!\n"; } } // const xxx&: 减少拷贝次数 void handleChildAndParent(const ParentPtr& p, const ChildPtr& c) { auto cp = c->father.lock(); auto pc = p->son.lock(); if (cp == p && pc == c) { cout << "right relation\n"; } else { cout << "oop!!!\n"; } } int main() { testParentAndChild(); return 0; }
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论