再论智能指针

以前写过一篇关于智能指针的文章,但是还是没有搞清楚两个东西:

1。智能指针如何调用被智能指针指向的对象的成员函数,我不知道如何只通过智能指针去访问指向对象的成员方法,请看我的写的智能指针的demo。

#include <iostream>
using namespace std; 
class A
{
private:
     int n;
public:
     A(int m):n(m) {} 
     ~A(){ cout<<"~A() is called\n"; }
 
     int get() const{ cout<<"get() is called\n"; }
};
 
class SmartPtr  //A的资源管理类,即智能指针类
{
private:
     A* a; 
public:
     B(A* b):a(b){ }     
     ~B(){ 
         delete a;  //在SmartPtr中释放A所占的内存
         cout<<"~B() is called\n";
     } 
     A* get() const{ return a; }   //好挫的方法通过返回被管理对象的指针来调用它的成员方法
}; 
int main(void)
{
     SmartPtr b(new A(8));
     A* a = b.get();  //不需要写delete(a),也不要写delete b
     int n = a->get();
     cout<<n<<endl;
     return 0;
}  

从上看出,我是通过在智能指针类中返回A的指针,然后还是通过指向A的指针来访问A中的方法,好挫。那么有什么更好的方法吗?有,重载->操作符即可。虽然我不知道重载->操作符为什么可以,但是确实给人感觉智能指针就是原指针。代码如下:

#include <iostream>
using namespace std;

class Test
{
private:
    int n;
public:
    Test(int m):n(m){}

    ~Test(){cout<<"~Test() is called\n";}

    void get()
    {
        cout<<"get() is called\n";
    }
};

class SmartPtr
{
private:
    Test* n;
public:
    SmartPtr(Test* m):n(m){}

    ~SmartPtr(){ cout<<"~SmartPtr is called\n"; delete n; n = NULL;}

    Test* operator->() const  //重载->操作符,通过SmartPtr调用Test类中方法犹如调用直接调用一般
    {
        return n;
    }
};

int main()
{
    {
   SmartPtr ptr(
new Test(10)); ptr->get(); //通过智能指针直接调用
  }
return 0; }

执行结果如下:

2。我想大家都认为智能指针,肯定是一个指针,就像int* ptr,ptr就是一个指针,而int ptr,而ptr就是一个非指针,其实智能指针非指针,它就如int ptr一样,下面让我来解释一下为什么吧?

首先我想说一下智能指针的原理,智能指针指向的对象不需要我们去delete,我们也不需要去delete智能指针,因为智能指针本身其实一个类,而类有new和非new进行创建对象,假设有一个智能指针类class SmartPtr,我们要这样去创建一个智能指针的对象:SmartPtr ptr(new Test()),而不是SmartPtr* ptr = new SmartPtr( ( new Test() ) ),为什么呢?因为智能指针是为了利用栈的对象在过程结束后自动调用析构函数的原理,SmartPtr ptr(new Test())是将ptr对象放在栈中,所以在任何一个过程结束后,自动调用SmartPtr的析构函数,只要我们在SmartPtr类中的析构函数去调用Test类的析构函数即可,而SmartPtr* ptr = new SmartPtr( ( new Test() ) )这种方法,过程结束后,ptr不会去自动调用SmartPtr的析构函数,需要我们程序员自己去delete,那么智能指针的意义就不复存在。

下面是一个使用SmartPtr* ptr = new SmartPtr( ( new Test() ) )这种方法去创建一个智能指针对象,我们可以上面的代码和图进行比较,

#include <iostream>
using namespace std;

class Test
{
private:
    int n;
public:
    Test(int m):n(m){}

    ~Test(){cout<<"~Test() is called\n";}

    void get()
    {
        cout<<"get() is called\n";
    }
};

class SmartPtr
{
private:
    Test* n;
public:
    SmartPtr(Test* m):n(m){}

    ~SmartPtr(){ cout<<"~SmartPtr is called\n"; delete n; n = NULL;}

    Test* operator->() const
    {
        return n;
    }
};


int main()
{
    {
    SmartPtr* ptr = new SmartPtr((new Test(10)));  //此时退出过程时,将不再自动调用析构函数
    }
    return 0;
}

运行截图如下:

对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。

原文地址:https://www.cnblogs.com/GODYCA/p/2863417.html