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 #include2 #include 3 #include 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.\n";12 }13 ~report() {14 std::cout << "Object deleted.\n";15 }16 void comment() const {17 std::cout << str << "\n";18 }19 };20 21 int main() {22 {23 std::auto_ptr ps(new report("using auto ptr"));24 ps->comment();25 }26 27 {28 std::shared_ptr ps(new report("using shared ptr"));29 ps->comment();30 }31 32 {33 std::unique_ptr ps(new report("using unique ptr"));34 ps->comment();35 }36 return 0;37 }
注意:智能指针的初始化必须使用复制初始化而不能采用赋值初始化,因为智能指针类的构造函数是explicit,只能够显示的调用构造函数
str_ptrp1 = new string("hello") //error,赋值初始化隐式调用构造函数str_ptr p2(new string("world")) //OK
unique_ptr注意拥有权必须用move
unique_ptrp2(new string("hello")); unique_ptr 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 #include2 #include 3 using namespace std; 4 5 template 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 24 smart_ptrs ::smart_ptrs(T *p) : count(new int(1)), p(p) {25 cout << "创建对象" << *p << ",引用计数:" << *count << endl;26 }27 28 template 29 //对普通指针进行拷贝,同时引用计数器加1,因为需要对参数进行修改,所以没有将参数声明为const30 smart_ptrs ::smart_ptrs(smart_ptrs &sp) : count(&(++*sp.count)), p(sp.p) {31 cout << "调用复制构造函数,拷贝:" << *sp.p << ",引用计数:" << *count << endl;32 }33 34 template 35 T* smart_ptrs ::operator->() {36 return p;37 }38 39 template 40 T& smart_ptrs ::operator*() {41 return *p;42 }43 44 template 45 smart_ptrs & smart_ptrs ::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 58 smart_ptrs ::~smart_ptrs() {59 if (--*count == 0) {60 delete count;61 delete p;62 }63 }64 65 int main()66 {67 smart_ptrs pstr(new string("abc"));68 smart_ptrs pstr2(pstr);69 smart_ptrs pstr3(new string("bcd"));70 pstr3 = pstr2;71 72 system("pause");73 }