- shared_ptr内部使用引用计数,每一个shared_ptr的拷贝都指向相同的内存,引用计数减为0时,自动释放所指向的堆内存。
- 不要用一个原始指针初始化多个shared_ptr,否则会二次释放同一内存。
- shared_ptr会出现循环引用问题,使用weak_ptr可以解决。
#include#include using namespace std; int main() { { // 初始化(推荐) shared_ptr ptr1 = make_shared (100); // 拷贝构造函数 shared_ptr ptr2(ptr1); cout << ptr1.use_count() << endl; // 2 int* p = new int(200); // 不能这样构造 //shared_ptr ptr3 = p; // 不能将普通指针直接赋值给一个智能指针 //ptr1 = p; // 初始化 shared_ptr ptr3(p); // 赋值运算符 ptr2 = ptr3; cout << ptr1.use_count() << endl; // 1 cout << ptr2.use_count() << endl; // 2 cout << ptr1.unique() << endl; // 1 // 获取原始指针 int* q = ptr3.get(); // 解引用运算符 cout << *ptr1 << endl; // 100 cout << *q << endl; // 200 swap(ptr1, ptr3); cout << *ptr1 << endl; // 200 cout << *ptr3 << endl; // 100 } system("pause"); return 0; }
当智能指针中有值时,调用reset()会使引用计数减1。当调用reset(new xxx())重新赋值时,智能指针首先是生成新对象,然后将就对象的引用计数减1,如果发现引用计数为0时,则析构旧对象,然后将新对象的指针交给智能指针保管。
#include2. unique_ptr#include using namespace std; class Person { public: Person(int id) :_id(id) { cout << "Constructor, id = " << _id << endl; } ~Person() { cout << "Destructor, id = " << _id << endl; } public: int _id; }; int main() { { shared_ptr p1 = make_shared (100); p1.reset(new Person(200)); // Destructor, id = 100 shared_ptr p2(p1); cout << p1.use_count() << endl; // 2 p1.reset(); cout << p2.use_count() << endl; // 1 } system("pause"); return 0; }
- 通过禁止拷贝语义、只有移动语义,实现同一时刻只能有一个unique_ptr指向给定对象。
- unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,默认使用delete操作符,用户可以自定义删除器。
#include3. weak_ptr#include using namespace std; class Person { public: Person(int id) :_id(id) { cout << "Constructor, id = " << _id << endl; } ~Person() { cout << "Destructor, id = " << _id << endl; } public: int _id; }; int main() { Person* p = new Person(100); // 不能这样构造 //unique_ptr ptr = p; unique_ptr ptr1(p); // ->运算符 cout << ptr1->_id << endl; // 100 ptr1.reset(); // Destructor, id = 100 //ptr = nullptr; // 这样也可以,Destructor, id = 100 unique_ptr ptr2(new Person(200)); // 不能将普通指针直接赋值给一个智能指针 //ptr = ptr2; // 不能拷贝构造 //unique_ptr ptr3(ptr2); { // 转移所有权 unique_ptr ptr4 = move(ptr2); cout << ptr4->_id << endl; // 200 } // Destructor, id = 200 unique_ptr ptr5(new Person(300)); // 释放所有权 Person* ptr = ptr5.release(); cout << ptr->_id << endl; // 300 // 注意delete! delete ptr; system("pause"); return 0; }
- weak_ptr辅助shared_ptr,解决shared_ptr可能出现的循环引用的问题。
- 它本身不能直接定义指向原始指针的对象,只能指向shared_ptr对象,同时也不能将weak_ptr对象直接赋值给shared_ptr类型的变量。
- 赋值给它不会增加引用计数!
// shared_ptr的循环引用问题 #include#include using namespace std; class CB; class CA { public: CA() { cout << "CA's Constructor" << endl; } ~CA() { cout << "CA's Destructor" << endl; } void set_ptr(shared_ptr & ptr) { m_ptr_b = ptr; } void b_use_count() { cout << "b use count : " << m_ptr_b.use_count() << endl; } private: shared_ptr m_ptr_b; }; class CB { public: CB() { cout << "CB's Constructor" << endl; } ~CB() { cout << "CB's Destructor" << endl; } void set_ptr(shared_ptr & ptr) { m_ptr_a = ptr; } void a_use_count() { cout << "a use count : " << m_ptr_a.use_count() << endl; } private: shared_ptr m_ptr_a; // 使用weak_ptr,解决循环引用问题 // weak_ptr m_ptr_a; }; int main() { { shared_ptr ptr_a(new CA); shared_ptr ptr_b(new CB); cout << "a use count : " << ptr_a.use_count() << endl; // 1 -> 1 cout << "b use count : " << ptr_b.use_count() << endl; // 1 -> 1 ptr_a->set_ptr(ptr_b); ptr_b->set_ptr(ptr_a); cout << "a use count : " << ptr_a.use_count() << endl; // 2 -> 1 cout << "b use count : " << ptr_b.use_count() << endl; // 2 -> 2 } system("pause"); return 0; }
-
使用shared_ptr可能出现循环引用的问题
-
使用weak_ptr解决循环引用问题
#include#include using namespace std; class Person { public: Person(int id) :_id(id) { cout << "Constructor, id = " << _id << endl; } ~Person() { cout << "Destructor, id = " << _id << endl; } void show() { cout << "Person, id = " << _id << endl; } public: int _id; }; void test01() { // 不能定义指向原始指针的weak_ptr //weak_ptr ptr_1(new Person(100)); shared_ptr ptr_1(new Person(100)); cout << ptr_1.use_count() << endl; // 1 shared_ptr ptr_2 = ptr_1; cout << ptr_1.use_count() << endl; // 2 cout << ptr_2.use_count() << endl; // 2 // weak_ptr不增加引用计数 weak_ptr wk_ptr = ptr_1; cout << ptr_1.use_count() << endl; // 2 cout << ptr_2.use_count() << endl; // 2 // 无法从“std::weak_ptr ”转换为“std::shared_ptr ” // shared_ptr ptr_3 = wk_ptr; } void test02() { shared_ptr ptr1(new Person(100)); shared_ptr ptr2(ptr1); cout << ptr1.use_count() << endl; // 2 weak_ptr wk_ptr = ptr1; cout << wk_ptr.use_count() << endl; // 2 if (!wk_ptr.expired()) { // 无->运算符 //wk_ptr->show(); wk_ptr.lock()->show(); } // 将wk_ptr1的置空 wk_ptr.reset(); if (wk_ptr.expired()) { cout << "wk_ptr is invalid" << endl; // 指针已经无效 } // 赋值运算符 wk_ptr = ptr2; if (!wk_ptr.expired()) { wk_ptr.lock()->show(); // 赋值操作后,指针有效 } } int main() { test01(); test02(); system("pause"); return 0; }
参考:https://blog.csdn.net/albertsh/article/details/82286999
参考:https://blog.csdn.net/shaosunrise/article/details/85158249



