Talking about auto_ptr intelligent pointer

Source: Internet
Author: User

Introduction of Smart pointers: the implementation principle of smart pointers: resource allocation is initialized RAII (Resource acquisition is initialization):

Define a class to encapsulate the allocation and release of resources, when the constructor completes the allocation and initialization of resources, and when the destructor completes the cleanup of resources, it can guarantee the proper initialization and release of the resources.
Implementation mechanism: The use of class constructs and destructors (releasing resources) is automatically invoked by the compiler.
Smart pointers: 1. Manage the release of the object to execute the pointer.
2. Can be used as a pointer.
There are four main smart pointers in the C + + standard library:
C + + Four kinds of smart pointers auto_ptr, Unique_ptr, shared_ptr and weak_ptr.
The auto_ptr is introduced by c++98 standardization, and Scope_ptr, shared_ptr and weak_ptr are introduced by C++11 standardization (which is already available in c++03 TR1, of course). As we all know, auto_ptr is simple, but it is so widely used that everyone is discouraged from using it. SHARED_PTR is a reference-counting smart pointer, a perfect stand-in for bare pointers, and is therefore widely used. It may also be that the scope_ptr and weak_ptr seem to have been forgotten (and perhaps considered superfluous).

The above comments are quoted from the Internet
Here's a quick summary of these smart pointers:

Design----->c++98/03 of 1.auto_ptr management right transfer with defects
Do not use under any circumstances;

2.scoped_ptr (Boost) unique_ptr (c++11) anti-copy---> Simple rough design---> dysfunction.
3, shared_ptr (boost/c++11) reference count---> powerful (support copy, custom remove) defect----> Circular Reference (weak_ptr).
The main content of this article is to explain a series of questions that auto_ptr leads to:

First, auto_ptr smart pointers
(no matter under what circumstances do not use, below to explain in detail why not use it, may be asked, since do not let use, then why should put it in the C + + standard library.) Yes, I had the same question at first,---> because the contents of C + + standard library are not allowed to be modified once stipulated.
The following simulation implements its basic functionality:
The first way to implement 1.AUTOPTR:

The use of resource transfer methods. A pointer gives the permissions of a piece of space completely to another pointer. (Transfer of permissions)


The simulation implementation code is as follows:
Template<class t>
class autoptr
{public
:
    autoptr (t* ptr = 0)//constructor
        : _ptr (PTR)
    {
        ptr = NULL;
    }

    Autoptr (autoptr<t>& AP)/Copy constructor
        : _ptr (ap._ptr)
    {
        ap._ptr = NULL;
    }

    autoptr<t>& operator= (autoptr<t>& AP)//assignment operator overload
    {
        if (this!= &ap)
        {
            if ( _ptr)
            {
                delete _ptr;
            }
            _ptr = ap._ptr;
            Ap._ptr = NULL;
        }
        return *this;
    }

    ~autoptr ()//destructor
    {
        if (_ptr)
        {
            delete _ptr;
            _ptr = NULL;
        }
    }

    t& operator* ()
    {return
        *_ptr;
    }

    t* operator-> ()
    {return
        _ptr;
    }
Private:
    t* _ptr;

void Test1 ()
{
    autoptr<int> ap (new int (1));
    Autoptr<int> AP1 (AP);
    Autoptr<int> AP2;
    AP2 = AP1;
}



There is a problem with the assignment operator: (This shows that the dynamic memory space can only be managed by a single smart pointer to avoid the following problems.)




The problem: Problem ①: The way to give a piece of space permission to someone else completely:
The problem is the copy construct and the assignment operator overloaded functions. When any one of the overloaded functions called the copy construct or assignment operator is invoked: Assuming that the copy constructor is invoked, we intend to use an object to construct an object that is exactly the same, but as a result, we have lost ourselves and completely failed to achieve our intended goal. So when we call the copy constructor in the Test1 in the above code, if we want to modify the contents of the object that was first constructed, we find that the object's resources have been cleaned up, so the program crashes.
Problem ②: First look at the following example:
#define _crt_secure_no_warnings 1 #include <iostream> using namespace std; 
    Template<class t> class Autoptr {public:autoptr (t* ptr = 0)//constructor: _ptr (ptr) {ptr = NULL;
    Autoptr (autoptr<t>& AP)//copy constructor: _ptr (ap._ptr) {ap._ptr = NULL;
            autoptr<t>& operator= (autoptr<t>& AP)//assignment operator overload {if (this!= &ap) {
            if (_ptr) {delete _ptr;
            } _ptr = Ap._ptr;
        Ap._ptr = NULL;
    return *this;
            } ~autoptr ()//destructor {if (_ptr) {delete _ptr;
        _ptr = NULL;
    } t& operator* () {return *_ptr;
    } t* operator-> () {return _ptr;
} private:t* _ptr;

};
    Autoptr<int> funtest () {autoptr<int> ap (new int (1));
Return AP; } void Test1 () {autoptr<int> ap (NEw Int (1));
    Autoptr<int> AP1 (AP);
    Autoptr<int> AP2;
    AP2 = AP1;
 Autoptr<int> AP4 (Funtest ());//The return value is returned as a value, then a temporary object,//temporary object has the constancy, so the parameters of the copy constructor should be modified by the const modifier when the copy constructs the AP4


Question ③:
The autoptr<int> ap (autoptr<int> (1))//brackets are constructs an unnamed object, the Nameless object, has the constancy, as the first ② question, when copies constructs the AP, The parameters of the copy constructor should be modified by the Const. Another problem is that, under VS2010, the compiler did some optimizations on it, which should have been a statement that called the constructor to construct the anonymous object and then the anonymous object to copy the construction object AP, but since the anonymous object was constructed, and immediately to copy the construction object, and is executed in a statement, so the compiler optimizes it, only calls the constructor, and does not call the copy constructor, the constructed nameless object value is given directly to the AP object, so the program does not crash under VS2010, And when you compile on Linux, you will report an error.
Here's my code for testing in Linux:


Compilation Error:



Summary: From the above compilation error we can learn that this is not realistic to copy the idea of a auto_ptr to construct a single object, so there is a third situation.
In fact, the implementation method three is to solve with a temporary right value object to copy the construction of an object.

The second way to implement 2.AUTOPTR:
Problem with wild pointers: The same example is used to analyze this problem:
Template<class t> class Autoptr {public:autoptr (t* ptr = 0)//constructor: _ptr (PTR), _owner (TRUE)//when
        Sets the exclusive resource to True {if (!_ptr) {_owner = false; } autoptr (const autoptr<t>& AP)//copy constructor: _ptr (Ap._ptr), _owner (true) {a
    P._owner = false;
            } autoptr& operator= (const autoptr<t>& AP)//assignment operator overload {if (this!= &ap) {
            Delete _ptr;
            _owner = true;
            _ptr = ap._ptr;
        Ap._owner = false;
    return *this;
            } ~autoptr () {if (_owner) {delete _ptr;
            _ptr = NULL;
        cout<< "~autoptr ()" <<endl;
    } t& operator* () {return *_ptr;
    } t* operator-> () {return _ptr;
    } private:t* _ptr;

mutable bool _owner;//can be modified}; void Testautoptr () {/*autoptr<int&Gt
    AP (new Int (10));
    Autoptr<int> AP1 (new int (20));
    Autoptr<int> AP2 (AP1);
    Autoptr<int> AP3;
    AP3 = ap;*/autoptr<int> AP4 (autoptr<int> (new int (20));
    if (true) {autoptr<int> ap5 (AP4);
    After the}//scope has been AP5, the space has been freed *AP4 = 10;//then AP5 shares a space with AP4, now that the AP5 has been freed, the AP4 object maintains a pointer that is a wild pointer to int main () {testautoptr ();
return 0; }

Memory leaks occur because AP4 and AP5 jointly manage a piece of space, when ap5 out the scope of the IF statement, has been destructor, the space is recycled, then in the following to visit the AP4 has a problem, AP4 has become a wild pointer.
③ type Conversion
C + + standard Library of the implementation of the AUTO_PTR: But there is a flaw: access to the null pointer problem can not be circumvented, that is, to achieve the first problem of the existence of a method
I first posted the source code in the standard library:
        TEMPLATE class Auto_ptr Template<class _ty> class auto_ptr; Template<class _ty> struct Auto_ptr_ref {//proxy reference for AUTO_PTR copying explicit

    R_ref (_ty *_right)//constructor: _ref (_right) {//construct from generic pointer to auto_ptr PTR}  _ty *_ref;

Generic pointer to auto_ptr PTR}; Template<class _ty> class Auto_ptr {//Wrap an object pointer to ensure destruction
    EF auto_ptr<_ty> _myt;
typedef _ty ELEMENT_TYPE; Generic constructor Explicit auto_ptr (_ty *_ptr = 0) _throw0 (): _myptr (_ptr) {//construct from Object point ER}//Generic copy constructor auto_ptr (_myt& _right) _throw0 (): _myptr (_right.release ()) {//Constr UCT by assuming pointer from _right AUTO_PTR}//with implicitly typed constructors auto_ptr (auto_ptr_ref<_ty> _right) _throw0 ( ) {//construct by assuming pointer from _right Auto_ptr_rEF _ty *_ptr = _right._ref;    _right._ref = 0;  Release old _myptr = _ptr;
        Reset this}//type conversion template<class _other> operator auto_ptr<_other> () _throw0 ()
        {//Convert to compatible auto_ptr return (auto_ptr<_other> (*this)); }//object type conversion template<class _other> operator auto_ptr_ref<_other> () _throw0 () {//Conver   T to compatible auto_ptr_ref _other *_cvtptr = _myptr;
        Test implicit conversion auto_ptr_ref<_other> _ans (_CVTPTR); _myptr = 0;
        Pass ownership to Auto_ptr_ref return (_ans); }//general assignment operator overloaded function Template<class _other> _myt& operator= (auto_ptr<_other>& _right) _THROW0 (
        ) {//Assign compatible _right (assume pointer) reset (_right.release ());
        return (*this); }//Copy constructor Template<class _other> auto_ptr (AUTO_PTR&LT;_OTHER&Gt;& _right) _throw0 (): _myptr (_right.release ()) {//construct by assuming pointer from _right }//General constructor _myt& operator= (_myt& _right) _throw0 () {//Assign compatible _right (assume Pointe
        R) Reset (_right.release ());
        return (*this); An assignment operator overloaded function with type conversion _myt& operator= (auto_ptr_ref<_ty> _right) _throw0 () {//Assign compatible-_r
        Ight._ref (assume pointer) _ty *_ptr = _right._ref;    _right._ref = 0;    Release old reset (_PTR);
        Set new return (*this);
        }//destructor ~auto_ptr () {//Destroy the object delete _myptr;
        _ty& operator* () const _throw0 () {//Return designated value #if _iterator_debug_level = 2
 if (_myptr = = 0) _debug_error ("Auto_ptr not dereferencable");
        #endif/* _iterator_debug_level = = 2/Return (*get ()); } _ty *operator-> () const_throw0 () {//return pointer to class object #if _iterator_debug_level = = 2 if (_myptr = = 0)
 _debug_error ("Auto_ptr not dereferencable");
        #endif/* _iterator_debug_level = = 2/* (get ());
        } _ty *get () const _throw0 () {//Return wrapped pointer return (_MYPTR); }//In order to transfer ownership _ty *release () _throw0 () {//return wrapped pointer and give up ownership _ty = _
        Myptr;
        _myptr = 0;
        return (_TMP); }//To receive ownership void Reset (_ty *_ptr = 0) {//Destroy designated object and store new pointer if (_ptr
        != _myptr) Delete _myptr;
        _myptr = _ptr;    Private: _ty *_myptr;
 The wrapped object pointer};


Sample Analysis:
#define _crt_secure_no_warnings 1
#include <iostream>
using namespace std;
#include <memory>

auto_ptr<int> funtest ()
{
    auto_ptr<int> ap1 (new int);
    Return ap1;//Returns a value of an anonymous object
}

void Test1 ()
{
    auto_ptr<int> ap1 (new int (10));//Constructor
    Auto_ Ptr<int> AP2 (new int (20));//constructor
    auto_ptr<int> ap3;
    AP3 = ap2;//assignment operator overload
    auto_ptr<int> AP4 (AP1);//Copy Construction
    auto_ptr<int> AP5 (Funtest ()); Type conversion occurs, Will go first to call this type of conversion function operator auto_ptr_ref<_other> (),
Then call the constructor auto_ptr (auto_ptr_ref<_ty> _right).
}

If you also want to know how the standard library is implemented, you can continue to look down, I hope you can help.


SOURCE Analysis:


























To simulate a generic pointer, the following two symbols are overloaded to make the smart pointer work like a generic pointer.



An original eco-pointer encapsulated within a smart pointer:





Second, scopedptr (exclusive space---> anti-copy, anti-assignment)
(In fact, in the C + + standard library called Unique_ptr, very well understood, because Autoptr is because of the transfer of resources, as well as referral permissions to cause a series of problems, traced in the end is the copy construction and assignment operators overloaded functions caused. So this smart pointer is a copy-and-assign-proof.
Because the AUTOPTR smart pointer has a slight problem with copy construction and assignment operator overloading, there is a scopedptr, since copy construction and assignment operator overloading can cause problems, so it is not allowed to copy and assign values.
Since copies and assignments are prone to problems, this smart pointer does not allow copying and assigning values.
Ways to solve the above problems:
There are three ways to implement this mechanism: 1 write the declaration of the copy constructor and assignment operator overloading the function as public, but do not define the two functions. 2 the copy constructor and assignment operator overload functions are implemented directly in the type, but their access qualifiers are set to private. 3 Write the declaration of the copy constructor and assignment operator overloading the function as private, but do not define the two functions.
Analysis of the above three methods:
The first: If you declare it to be public, then if there are other people outside the class for your copy construction and assignment operator overloaded functions, then still do not meet the requirements of copy-proof, anti-assignment. --->pass off the second: personally feel, since all have not allowed to copy and assign value, why should also be superfluous to write out its implementation method. So----->pass off. So: It's appropriate for the third method.
Here I only post the code for the third method:

Anti-copy, anti-assignment
template<class t>
class scopedptr
{public
:
    scopedptr (t* ptr)//constructor
        : _ptr (PTR)
    {}
    ~scopedptr ()//destructor
    {
        if (NULL!= _ptr)
        {
            delete _ptr;
            _ptr = NULL;
        }
    }

    t& operator* ()
    {return
        *_ptr;
    }

    t* operator-> ()
    {return
        _ptr;
    }
Private:
    scopedptr (const scopedptr& AP);//copy Constructor declaration
    scopedptr& operator= (const scopedptr& AP) ;//Assignment operator overloaded function declaration
    t* _ptr;

void Test1 ()
{
    scopedptr<int> SP1 (new int);
    *SP1 =;
}

scoped_array//Management Array
(in the Boost library, the C + + standard library is not added because it already has a vector of similar functions)
Manage Arrays (anti-copy, anti-assignment)
template<class t>
class Scopedarray
{public
:
    scopedarray (t* ptr = 0)// Constructor
        : _ptr (PTR)
    {}
    ~scopedarray ()//destructor
    {
        if (NULL!= _ptr)
        {
            delete[] _ptr;
            _ptr = NULL;
        }
    }
Basic Operation
    t& operator* ()
    {return
        *_ptr;
    }
Basic Operation
    t* operator-> ()
    {return
        _ptr;
    }
Basic operations
    t& operator[] (size_t index)
    {return
        _ptr[index];
    }
Private:
    scopedarray (const scopedarray<t>& AP);
    scopedarray& operator= (const scopedarray<t>& AP);
    t* _ptr;
};

Summary: The smart pointers in the C + + standard library can only manage the dynamic space of a single object, not allow it to manage a contiguous space, such as a dynamically opened array of space.
Auto_ptr no matter when the use of scoped_ptr is a solution to the problems of auto_ptr. So the general interview, there is no special designation for you to achieve which smart pointers, it is best to write this, because this is the simplest ah, do not write auto_ptr, this smart pointer is flawed.
Although the C + + standard library has added a auto_ptr smart pointer, do not use it, the C + + standard library still retains it, should be for forward compatibility. Since it has been added to the standard library, it will certainly be used by programmers, so still can not be discarded.
I will also continue to summarize the implementation details about shared_ptr.


Digression:
Because the beginning of contact with the smart pointer, their own capacity is insufficient, so where to write a question welcome everyone to come forward. Common progress. Make a little progress every day.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.