Simple implementation of the Smart Pointer class

In the book, C++ Primer 13.5.1he realizes the smart pointer class with class-use graph . Their implementation is as follows:

  • Graph usage class

    // private class for use by HasPtr only
    class U_Ptr {
        friend class HasPtr;
        int *ip;
        size_t use;
        U_Ptr(int *p): ip(p), use(1) { }
        ~U_Ptr() { delete ip; }
    };
    
  • Smart pointer class

    /* 
       smart pointer class: takes ownership of the dynamically allocated
       object to which it is bound
    
       User code must dynamically allocate an object to initialize a HasPtr
       and must not delete that object; the HasPtr class will delete it
    */
    class HasPtr {
    public:
        // HasPtr owns the pointer; p must have been dynamically allocated
        HasPtr(int *p, int i)
            : ptr(new U_Ptr(p)), val(i) { }
    
        // copy members and increment the use count
        HasPtr(const HasPtr &orig)
            : ptr(orig.ptr), val(orig.val) { ++ptr->use; }
    
        HasPtr& operator=(const HasPtr&);
    
        // if use count goes to zero, delete the U_Ptr object
        ~HasPtr() { if (--ptr->use == 0) delete ptr; } 
    
        friend ostream& operator<<(ostream&, const HasPtr&);
        // copy control and constructors as before
    
        // accessors must change to fetch value from U_Ptr object
        int *get_ptr() const { return ptr->ip; } 
        int get_int() const { return val; }
    
        // change the appropriate data member
        void set_ptr(int *p) { ptr->ip = p; }
        void set_int(int i) { val = i; }
    
        // return or change the value pointed to, so ok for const objects
        // Note: *ptr->ip is equivalent to *(ptr->ip)
        int get_ptr_val() const { return *ptr->ip; } 
        void set_ptr_val(int i) { *ptr->ip = i; }
    private:
        U_Ptr *ptr;        // points to use-counted U_Ptr class
        int val;
    };
    

Wonder . I am wondering why it is not easy to use int *for work as Use-Count Class, as well as int* countPtr;used in the following new Smart Pointer Class:

class T
{
private:
    int* countPtr; //

    int* p;
    int val;

public:
    T(){
        p = new int();
        countPtr = new int();
        *countPtr = 1;
        val = 0;
    }
    T(T& t){
        p = t.p;
        countPtr = t.countPtr;
        val = t.val;
        *countPtr += 1;
    }
    T& operator = ( const T& rT){
        if(*countPtr>1){
            *countPtr -= 1;
        }
        else{
            delete p;
            delete countPtr;
        }
        p = rT.p;
        countPtr = rT.countPtr;
        val = rT.val;
        *countPtr += 1;
        return *this;
    }
    ~T(){
        if(*countPtr>1){
            *countPtr -= 1;
        }
        else{
            delete p;
            delete countPtr;
        }
    }

    int *get_ptr() const { return p; } 
    int get_int() const { return val; }

    // change the appropriate data member
    void set_ptr(int *ptr) { p = ptr; }
    void set_int(int i) { val = i; }
};

Test . I tested the above Smart Pointer Classusing the following code and it seems to work well.

int main()
{
    T t1;
    T t2(t1);
    T t3(t1);
    T t4;
    t4 = t1;

    return 0;
}

The real question is : is this new enough Smart Pointer Classjust a int *countPtr? If so, why bother using extra Use-Count Class, as in the book? If not, what will I miss?

+4
4

, delete . . , , , delete - .

, , , , , , .

, , , delete , .

, std::shared_ptr () , , - .

+5

, . :

  • / ( int ). .

  • , . : , , .

  • ( )

:

  • , . , ...
+2

, - - , , :

  • ( , - , , () , , , )

  • , ( ),

  • (, boost:: shared_ptr #ifdef )

  • , , , OS- (. boost/smart_ptr/detail/sp_counted_base _ *. hpp)

, , , , U_Ptr....

+2

( 14.4.2017)

unique_ptr shared_ptr , , . API, Object*& - (), . ++ 11, . ( * _ptr )

?

auto_ptr, , , , .

, - , google - :

http://www.codingwisdom.com/codingwisdom/2012/09/reference-counted-smart-pointers-are-for-retards.html

, , , , C .

, , svn: https://sourceforge.net/p/testcppreflect/code/HEAD/tree/SmartPtr.h

.

#pragma once

//
// If you're using multithreading, please make sure that two threads are not accessing 
// SmartPtr<> pointers which are cross linked.
//
template <class T>
class SmartPtr
{
public:
    SmartPtr() : ptr( nullptr ), next( nullptr )
    {
    }

    SmartPtr( T* pt ) : ptr( pt ), next( nullptr )
    {
    }

    SmartPtr( SmartPtr<T>& sp ) : ptr( nullptr ), next( nullptr )
    {
        operator=(sp);
    }

    ~SmartPtr()
    {
        release();
    }

    // Reference to pointer - assumed to be filled out by user.
    T*& refptr()
    {
        release();
        return ptr;
    }

    // Pointer itself, assumed to be used.
    T* get()
    {
        return ptr;
    }

    T* operator->() const
    {
        return ptr;
    }

    T* operator=( T* _ptr )
    {
        release();
        ptr = _ptr;
        return ptr;
    }

    SmartPtr<T>& operator=( SmartPtr<T>& sp )
    {
        release();
        ptr = sp.ptr;

        if ( ptr )      // If we have valid pointer, share ownership.
        {

            if( sp.next == nullptr )
            {
                next = &sp;
                sp.next = this;
            } else {
                SmartPtr<T>* it = &sp;

                while( it->next != &sp )
                    it = it->next;

                next = &sp;
                it->next = this;
            }
        }

        return *this;
    }

    void release()
    {
        if ( !ptr )
            return;

        // Shared ownership.
        if( next != nullptr )
        {
            // Remove myself from shared pointer list.
            SmartPtr<T>* it = next;

            while( it->next != this )
                it = it->next;

            if( it == it->next->next )
                it->next = nullptr;
            else
                it->next = next;

            next = nullptr;
            ptr = nullptr;
            return;
        }

        // Single user.
        delete ptr;
        ptr = nullptr;
    }

    T* ptr;                 // pointer to object
    SmartPtr<T>* next;      // nullptr if pointer is not shared with anyone, 
                            // otherwise cyclic linked list of all SmartPtr referencing that pointer.
};

, , , .

* refptr(), . ( "++ jewels" )

, , - , .: -)

.

:

: Smart Pointer int * countPtr ? , , Use-Count ? , ?

, , - ​​ . , ( ), - (), .

- , , , , . , . , .

For memory leaks, I recommend finding existing tools and using them - for example, this one:

https://sourceforge.net/projects/diagnostic/

(There are many, but none of them works reliably / well enough).

I know that you want to dislike this implementation, but in reality - please tell me what obstacles you see in this implementation ?!

-2
source

All Articles