zoukankan      html  css  js  c++  java
  • Smart Pointer 智能指针

    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 }
  • 相关阅读:
    java基础多线程
    java反射基础
    JSP-4(Session)
    JSP-3
    JSP-2
    复试计算机专业文献翻译
    jsp
    实现输入输出对应模型
    servlet
    tomcat的入门(1)
  • 原文地址:https://www.cnblogs.com/raichen/p/5697235.html
Copyright © 2011-2022 走看看