P76
参考:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html
http://blog.csdn.net/hackbuteer1/article/details/7561235
简介
智能指针是存储指向动态分类(堆)对象的指针的类,用于生存期控制,确保在离开指针作用域时,自动正确销毁动态分配的对象。
通过引用计数的技术来实现,每使用它一次,内部的引用计数就加1,每析构一次,引用计数减1,减到0时就销毁对象,回收内存。
头文件 #include <memory>
分类
三种智能指针:
- std::shared_ptr 实现共享式拥有,多个指针可以指向相同的对象,该对象和相关资源会在最后一个reference被销毁时释放
- std::unique_ptr 实现独占式拥有,保证同一时间内只有一个指针可以指向该对象
- std::weak_ptr 持有被shared_ptr所管理对象的引用,但是不会改变引用计数值。允许共享但不拥有某对象
另一方面,auto_ptr已经被废弃,C98,之前和std::unique_ptr一个意思
使用
1 #include <iostream> 2 #include <string> 3 #include <memory> 4 5 class report 6 { 7 private: 8 std::string str; 9 public: 10 report(const std::string s) : str(s) { 11 std::cout << "Object created. "; 12 } 13 ~report() { 14 std::cout << "Object deleted. "; 15 } 16 void comment() const { 17 std::cout << str << " "; 18 } 19 }; 20 21 int main() { 22 { 23 std::auto_ptr<report> ps(new report("using auto ptr")); 24 ps->comment(); 25 } 26 27 { 28 std::shared_ptr<report> ps(new report("using shared ptr")); 29 ps->comment(); 30 } 31 32 { 33 std::unique_ptr<report> ps(new report("using unique ptr")); 34 ps->comment(); 35 } 36 return 0; 37 }
注意:智能指针的初始化必须使用复制初始化而不能采用赋值初始化,因为智能指针类的构造函数是explicit,只能够显示的调用构造函数
str_ptr<string> p1 = new string("hello") //error,赋值初始化隐式调用构造函数 str_ptr<string> p2(new string("world")) //OK
unique_ptr注意拥有权必须用move
unique_ptr<string> p2(new string("hello")); unique_ptr<string> p3; p3 = std::move(p2);
p2失去拥有权不能在被调用了
unique_ptr比auto_ptr的好处在于如果p3 = p2,unique_ptr在编译时就能发现错误,auto_ptr要在运行时才能发现错误
shared_ptr实现
参考:http://www.jianshu.com/p/0300b2d833af
分析:
成员,一个模板指针T *p,一个引用计数的int *count;
成员函数:
构造函数:接受T *参数初始化成员p,初始化count为1,注意count需要new,p就不用了,p是在使用过程中new的
复制构造函数:注意形参不要用const类型,是引用类型的smart_point类,让count等于形参.count++,让p等于形参.p
析构函数:首先先对*count自减,不是0就算了,是0的话delete p和count
然后写重载几个运算符*,->和=
*是返回T&类型,返回*p
->返回T*类型也就是指针,返回的是p
=首先将*count加一,然后为了防止自己=自己要判断count自减后是不是0,最后用对count和p进行赋值操作
1 #include <string> 2 #include <iostream> 3 using namespace std; 4 5 template <typename T> 6 class smart_ptrs { 7 8 public: 9 smart_ptrs(T*); //用普通指针初始化智能指针 10 smart_ptrs(smart_ptrs&); 11 12 T* operator->(); //自定义指针运算符 13 T& operator*(); //自定义解引用运算符 14 smart_ptrs& operator=(smart_ptrs&); //自定义赋值运算符 15 16 ~smart_ptrs(); //自定义析构函数 17 18 private: 19 int *count; //引用计数 20 T *p; //智能指针底层保管的指针 21 }; 22 23 template <typename T> 24 smart_ptrs<T>::smart_ptrs(T *p) : count(new int(1)), p(p) { 25 cout << "创建对象" << *p << ",引用计数:" << *count << endl; 26 } 27 28 template <typename T> 29 //对普通指针进行拷贝,同时引用计数器加1,因为需要对参数进行修改,所以没有将参数声明为const 30 smart_ptrs<T>::smart_ptrs(smart_ptrs &sp) : count(&(++*sp.count)), p(sp.p) { 31 cout << "调用复制构造函数,拷贝:" << *sp.p << ",引用计数:" << *count << endl; 32 } 33 34 template <typename T> 35 T* smart_ptrs<T>::operator->() { 36 return p; 37 } 38 39 template <typename T> 40 T& smart_ptrs<T>::operator*() { 41 return *p; 42 } 43 44 template <typename T> 45 smart_ptrs<T>& smart_ptrs<T>::operator=(smart_ptrs& sp) { 46 ++*sp.count; 47 if (--*count == 0) { //自我赋值同样能保持正确 48 delete count; 49 delete p; 50 } 51 this->p = sp.p; 52 this->count = sp.count; 53 cout << "赋值操作," << *this->p << "引用计数变为" << *this->count << endl; 54 return *this; 55 } 56 57 template <typename T> 58 smart_ptrs<T>::~smart_ptrs() { 59 if (--*count == 0) { 60 delete count; 61 delete p; 62 } 63 } 64 65 int main() 66 { 67 smart_ptrs<string> pstr(new string("abc")); 68 smart_ptrs<string> pstr2(pstr); 69 smart_ptrs<string> pstr3(new string("bcd")); 70 pstr3 = pstr2; 71 72 system("pause"); 73 }