• c++ smart pointer


    智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。它的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
        智能指针就是模拟指针动作的类。所有的智能指针都会重载 -> 和 * 操作符。智能指针还有许多其他功能,比较有用的是自动销毁。这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。当然,智能指针还不止这些,还包括复制时可以修改源对象等。智能指针根据需求不同,设计也不同(写时复制,赋值即释放对象拥有权限、引用计数等,控制权转移等)。auto_ptr 即是一种常见的智能指针。
         智能指针通常用类模板实现:

    template <class T>
    class smartpointer
    {
    private:
        T *_ptr;
    public:
        smartpointer(T *p) : _ptr(p)  //构造函数
        {
        }
        T& operator *()        //重载*操作符
        {
            return *_ptr;
        }
        T* operator ->()       //重载->操作符
        {
            return _ptr;
        }
        ~smartpointer()        //析构函数
        {
            delete _ptr;
        }
    };

    下面我们定义一个Person类:

    class Person
    {
        int age;
        char* pName;
    
        public:
            Person(): pName(0),age(0)
            {
            }
            Person(char* pName, int age): pName(pName), age(age)
            {
            }
            ~Person()
            {
            }
    
            void Display()
            {
                printf("Name = %s Age = %d 
    ", pName, age);
            }
            void Shout()
            {
                printf("Ooooooooooooooooo",);
            } 
    };

    这么调用:

    void main()
    {
        SP<PERSON> p(new Person("Scott", 25));
        p->Display();
        {
            SP<PERSON> q = p;
            q->Display();
            // Destructor of Q will be called here..
        }
        p->Display();
    }
    Look what happens here. p and q are referring to the same Person class pointer. Now when q goes out of scope, the destructor of q will be called which deletes the Person class pointer. Now we cannot call p->Display(); since p will be left with a dangling pointer and this call will fail. (Note that this problem would have existed even if we were using normal pointers instead of smart pointers.) We should not delete the Person class pointer unless no body is using it. How do we do that? Implementing a reference counting mechanism in our smart pointer class will solve this problem.

    What we are going to do is we will have a reference counting class RC. This class will maintain an integer value which represents the reference count. We will have methods to increment and decrement the reference count.
    我们写一个RC类:
    class RC
    {
        private:
        int count; // Reference count
    
        public:
        void AddRef()
        {
            // Increment the reference count
            count++;
        }
    
        int Release()
        {
            // Decrement the reference count and
            // return the reference count.
            return --count;
        }

    Now that we have a reference counting class, we will introduce this to our smart pointer class. We will maintain a pointer to class RC in our SP class and this pointer will be shared for all instances of the smart pointer which refers to the same pointer. For this to happen, we need to have an assignment operator and copy constructor in our SP class.

    template < typename T > class SP
    {
    private:
        T*    pData;       // pointer
        RC* reference; // Reference count
    
    public:
        SP() : pData(0), reference(0) 
        {
            // Create a new reference 
            reference = new RC();
            // Increment the reference count
            reference->AddRef();
        }
    
        SP(T* pValue) : pData(pValue), reference(0)
        {
            // Create a new reference 
            reference = new RC();
            // Increment the reference count
            reference->AddRef();
        }
    
        SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
        {
            // Copy constructor
            // Copy the data and reference pointer
            // and increment the reference count
            reference->AddRef();
        }
    
        ~SP()
        {
            // Destructor
            // Decrement the reference count
            // if reference become zero delete the data
            if(reference->Release() == 0)
            {
                delete pData;
                delete reference;
            }
        }
    
        T& operator* ()
        {
            return *pData;
        }
    
        T* operator-> ()
        {
            return pData;
        }
        
        SP<T>& operator = (const SP<T>& sp)
        {
            // Assignment operator
            if (this != &sp) // Avoid self assignment
            {
                // Decrement the old reference count
                // if reference become zero delete the old data
                if(reference->Release() == 0)
                {
                    delete pData;
                    delete reference;
                }
    
                // Copy the data and reference pointer
                // and increment the reference count
                pData = sp.pData;
                reference = sp.reference;
                reference->AddRef();
            }
            return *this;
        }
    };

    客户端调用:

    void main()
    {
        SP<PERSON> p(new Person("Scott", 25));
        p->Display();
        {
            SP<PERSON> q = p;
            q->Display();
            // Destructor of q will be called here..
    
            SP<PERSON> r;
            r = p;
            r->Display();
            // Destructor of r will be called here..
        }
        p->Display();
        // Destructor of p will be called here 
        // and person pointer will be deleted
    }

    When we create a smart pointer p of type Person, the constructor of SP will be called, the data will be stored, and a new RC pointer will be created. The AddRef method of RC is called to increment the reference count to 1. Now SP q = p; will create a new smart pointer q using the copy constructor. Here the data will be copied and the reference will again be incremented to 2. Now r = p; will call the assignment operator to assign the value of p to q. Here also we copy the data and increment the reference count, thus making the count 3. When r and q go out of scope, the destructors of the respective objects will be called. Here the reference count will be decremented, but data will not be deleted unless the reference count becomes zero. This happens only when the destructor of p is called. Hence our data will be deleted only when no body is referring to it.

    上面的参考了http://www.codeproject.com/Articles/15351/Implementing-a-simple-smart-pointer-in-c

    这篇文章。

    http://zh.wikipedia.org/wiki/%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88 

    http://www.informit.com/articles/article.aspx?p=25264

    http://ootips.org/yonat/4dev/smart-pointers.html

    http://stackoverflow.com/questions/22585974/smart-pointer-implementation

    http://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one

     另一篇比较好的文章:

    http://blog.csdn.net/hackbuteer1/article/details/7561235

  • 相关阅读:
    性能指标有哪些?
    Jmeter获取数据库数据
    jmeter用什么查看结果报告
    jmeter中assertion的使用
    jmeter进行压测的步骤
    Jenkins 构建方式有几种
    Redis数据类型
    敏捷 还是瀑布 敏捷优缺点
    如何加快数据库查询速度
    智力题总结
  • 原文地址:https://www.cnblogs.com/youxin/p/3669994.html
Copyright © 2020-2023  润新知