[C++]Shared_ptr使用详解&&实现链表
2016-06-09 01:13
666 查看
Shared_ptr使用详解
在之前参加项目时,有一条准则为不使用原生态指针,而使用智能指针。那么我将在本文中介绍shard_ptr的内容。本文分两个部分组成,第一部分是讲解shard_ptr的使用方法,(至于智能指针的理解,此处不赘述)以及第二部分使用shared_ptr实现链表的部分功能,(其他功能也是类似的而已)。(知识点摘自cplusplus)
构造部分
构造函数有4个参数分别有以下含义:![](http://o7d2h0gjo.bkt.clouddn.com/2016-06-09-para.png)
#include <algorithm> #include <iostream> #include <memory> using namespace std; /* default (1) constexpr shared_ptr() noexcept; from null pointer (2) constexpr shared_ptr(nullptr_t) : shared_ptr() {} from pointer (3) template <class U> explicit shared_ptr (U* p); with deleter (4) template <class U, class D> shared_ptr (U* p, D del); template <class D> shared_ptr (nullptr_t p, D del); with allocator (5) template <class U, class D, class Alloc> shared_ptr (U* p, D del, Alloc alloc); template <class D, class Alloc> shared_ptr (nullptr_t p, D del, Alloc alloc); copy (6) shared_ptr (const shared_ptr& x) noexcept; template <class U> shared_ptr (const shared_ptr<U>& x) noexcept; copy from weak (7) template <class U> explicit shared_ptr (const weak_ptr<U>& x); move (8) shared_ptr (shared_ptr&& x) noexcept; template <class U> shared_ptr (shared_ptr<U>&& x) noexcept; move from managed (9) template <class U> shared_ptr (auto_ptr<U>&& x); template <class U, class D> shared_ptr (unique_ptr<U,D>&& x); aliasing (10) template <class U> shared_ptr (const shared_ptr<U>& x, element_type* p) noexcept; */ struct C { int* data; }; int main() { std::shared_ptr<int> p1; std::shared_ptr<int> p2(nullptr); std::shared_ptr<int> p3(new int); std::shared_ptr<int> p4(new int, std::default_delete<int>()); std::shared_ptr<int> p5(new int, [](int* p) { delete p; }, std::allocator<int>()); std::shared_ptr<int> p6(p5); std::shared_ptr<int> p7(std::move(p6)); std::shared_ptr<int> p8(std::unique_ptr<int>(new int)); std::shared_ptr<C> obj(new C); std::shared_ptr<int> p9(obj, obj->data); std::cout << "use_count:\n"; std::cout << "p1: " << p1.use_count() << '\n'; std::cout << "p2: " << p2.use_count() << '\n'; std::cout << "p3: " << p3.use_count() << '\n'; std::cout << "p4: " << p4.use_count() << '\n'; std::cout << "p5: " << p5.use_count() << '\n'; std::cout << "p6: " << p6.use_count() << '\n'; std::cout << "p7: " << p7.use_count() << '\n'; std::cout << "p8: " << p8.use_count() << '\n'; std::cout << "p9: " << p9.use_count() << '\n'; return 0; }
operator=
make_shared和
move两个函数可以用于operator=操作。
![](http://o7d2h0gjo.bkt.clouddn.com/2016-06-09-para1.png)
/* copy (1) shared_ptr& operator= (const shared_ptr& x) noexcept; template <class U> shared_ptr& operator= (const shared_ptr<U>& x) noexcept; move (2) shared_ptr& operator= (shared_ptr&& x) noexcept; template <class U> shared_ptr& operator= (shared_ptr<U>&& x) noexcept; move from (3) template <class U> shared_ptr& operator= (auto_ptr<U>&& x); template <class U, class D> shared_ptr& operator= (unique_ptr<U,D>&& x); */ #include <iostream> #include <memory> int main() { std::shared_ptr<int> foo; std::shared_ptr<int> bar(new int(10)); foo = bar; // copy bar = std::make_shared<int>(20); // move std::unique_ptr<int> unique(new int(30)); foo = std::move(unique); // move from unique_ptr std::cout << "*foo: " << *foo << '\n'; std::cout << "*bar: " << *bar << '\n'; return 0; }
reset操作
回收内存并且改变内存。![](http://o7d2h0gjo.bkt.clouddn.com/2016-06-09-para2.png)
/* void reset() noexcept; template <class U> void reset (U* p); template <class U, class D> void reset (U* p, D del); template <class U, class D, class Alloc> void reset (U* p, D del, Alloc alloc); */ #include <iostream> #include <memory> int main() { std::shared_ptr<int> sp; // empty sp.reset(new int); // takes ownership of pointer *sp = 10; std::cout << *sp << '\n'; sp.reset(new int); // deletes managed object, acquires new pointer *sp = 20; std::cout << *sp << '\n'; sp.reset(); // deletes managed object return 0; }
make_share
构造内存。/* template <class T, class... Args> shared_ptr<T> make_shared (Args&&... args); */ #include <iostream> #include <memory> int main() { std::shared_ptr<int> foo = std::make_shared<int>(10); // same as: std::shared_ptr<int> foo2(new int(10)); auto bar = std::make_shared<int>(20); auto baz = std::make_shared<std::pair<int, int>>(30, 40); std::cout << "*foo: " << *foo << '\n'; std::cout << "*bar: " << *bar << '\n'; std::cout << "*baz: " << baz->first << ' ' << baz->second << '\n'; return 0; }
allocate_shared
![](http://o7d2h0gjo.bkt.clouddn.com/2016-06-09-para3.png)
/* template <class T, class Alloc, class... Args> shared_ptr<T> allocate_shared (const Alloc& alloc, Args&&... args); */ #include <iostream> #include <memory> int main () { std::allocator<int> alloc; // the default allocator for int std::default_delete<int> del; // the default deleter for int std::shared_ptr<int> foo = std::allocate_shared<int> (alloc,10); auto bar = std::allocate_shared<int> (alloc,20); auto baz = std::allocate_shared<std::pair<int,int>> (alloc,30,40); std::cout << "*foo: " << *foo << '\n'; std::cout << "*bar: " << *bar << '\n'; std::cout << "*baz: " << baz->first << ' ' << baz->second << '\n'; return 0; }
shared_ptr实现链表
#include <iostream> #include <memory> using namespace std; template <typename T> struct node { T value; shared_ptr<node> next; node(T val = 0, shared_ptr<node> n = nullptr) : value(val), next(n) {} }; template <typename T> class list { private: typedef shared_ptr<node<T>> pointer; typedef T value_type; private: pointer head; size_t size; public: list() : head(make_shared<node<T>>()), size(0) {} ~list() {} void push_back(const value_type& val) { pointer temp = head; if (temp.get()->next != nullptr) { temp = temp.get()->next; } auto temps = make_shared<node<T>>(val); (*temp.get()).next = temps; size++; } void push_front(const value_type& val) { pointer temp = make_shared<node<T>>(0, head); head.get()->value = val; head = temp; size++; } bool insert(int pos, const value_type& val) { if (pos == 0) { push_front(val); return true; } if (pos == size - 1) { push_back(val); return true; } if (pos > size) { return false; } else { pointer temp = head.get()->next; for (int i = 0; i != pos; i++) { temp = temp.get()->next; } pointer add = make_shared<node<T>>(val, nullptr); temp.get()->next = add; size++; return true; } } bool erase(int pos) { if (pos == 0) { head = head.get()->next; size--; return true; } if (pos >= size) { return false; } else { pointer del = head.get()->next; for (int i = 0; i != pos - 1; i++) { del = del.get()->next; } del.get()->next = del.get()->next->next; size--; return true; } } friend ostream& operator<<(ostream& out, list<T> & orig) { pointer temp = orig.head.get()->next; while (temp.get()->next != nullptr) { out << temp.get()->value << " "; temp = temp.get()->next; } out << temp.get()->value << endl; return out; } }; int main() { list<int> li; li.push_back(10); li.push_back(123); li.push_front(12); li.insert(0, 20); li.erase(2); cout << li; return 0; }
![](http://o7d2h0gjo.bkt.clouddn.com/2016-06-09-test2.png)
这个
shared_ptr的链表实现版本比我想象中要出现更多的问题,最主要的问题是我夸大了
shared_ptr的内存管理能力。一开始我以为
shared_ptr的对象只要到达使用析构函数的部分,不管他的引用计数为多少都会被回收资源(因为他们不会再被使用)。但实际情况并不是如此,并没有这么智能!到达析构函数时,如果引用计数大于1,那么他们只会调用-1的操作,并不会直接忽略引用计数而直接析构资源。(细想一下,确实应当如此。)基于最初的妄想,我设计了一个双头链表(有
next和
prev对象),最后出现了大量的内存泄露。最后我把node设计为单向链表,然后就没有内存泄露了。
虽然使用智能指针仍然要考虑引用计数的问题,但还是应该承认使用智能指针确实比使用原生态的指针方便太多,特别是在erase元素的时候。
相关文章推荐
- C/C++二维数组的用法
- ACM:蓝桥杯:三个数从小到大排列
- C语言/指针
- ACM:蓝桥杯:韩信点兵
- ACM:蓝桥杯:斐波那契数
- 实现memcpy、memcpy的优化、memmove、memset、strcpy、strncpy
- ACM:蓝桥杯:n-1位数
- C语言的字符串(篇章之二)
- [置顶] 【VSCode】Windows下VSCode编译调试c/c++【更新】
- C++独孤九剑第四式——菩提无树(构造函数语意)
- c语言 用链表构造字符串
- L1-011. A-B
- 一个web服务器并发测试工具 (含源码)
- c语言实例之函数副本机制
- c++:静态函数成员与静态数据成员
- c++:静态函数成员与静态数据成员
- 【C++】Visual Studio 2012 MFC中添加OnTimer时间函数
- 深入探索c++虚函数继承模型
- C++第二次上机5-5
- c++ string函数精讲