C++ 几种智能指针的简单实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 几种智能指针的简单实现相关的知识,希望对你有一定的参考价值。

#pragma once

// 智能指针 

// 定义个类来封装资源的分配和释放,在构造 函数完成资源的分配和初始化,在析构函数完成资源的

// 清理,可以 保证资源的正确初始化和释放。

// 这里简单实现 AutoPtr、 ScopedPtr、ScopedArray以及 SharedPtr


 //------------------------------SmartPtr.h-------------------

template<typename T>

class AutoPtr //缺点 定义多个指向同一空间的ptr 只有一个控制 其他的都失效了 

{

public:

    AutoPtr(T* ptr = NULL)

        :_ptr(ptr)

    {}


    AutoPtr(AutoPtr<T>& ap)// 这里没有用const 为了修改ap的成员

        :_ptr(ap._ptr)

    {

        ap._ptr = NULL;// 只能有一个智能指针 指向空间 (控制权

    }

    

    AutoPtr<T>& operator= (AutoPtr<T>& ap)

    {

        if(_ptr != ap._ptr)//排除 1 自赋值 2(常常会忽略) 虽然不是自赋值 但两个的_ptr 指向同一空间

        {

            //第3种情况 两个不指向同一空间

            delete _ptr;

            _ptr = ap._ptr;

            ap._ptr = NULL;


            return *this;

        }

    }


    ~AutoPtr()

    {

        if(_ptr)

        {

            cout<<"delete _ptr"<<_ptr<<endl;

            delete _ptr;

        }

    }


    T& operator*()

    {

        return *_ptr;

    }

    // 从原理来说 要两个-> 

    // operator->()返回的是T* 再->才能访问对应成员

    // 这里编译器做了处理

    // 如 operator++() operator++(int)

    T* operator->()

    {

        return _ptr;

    }


protected:

    T* _ptr;

};


void testAutoPtr()

{


    struct A

{

    int _a;

};


    AutoPtr<int> ap1(new int(1));

    AutoPtr<int> ap2(ap1);

    AutoPtr<int> ap3(new int(2));

    ap3 = ap2;


    *ap3 = 10;//运算符重载T& operator*()


    A* p4 = new A;

    p4->_a = 10;


    AutoPtr<A> ap4(new A);//运算符重载 T* operator->()

    ap4->_a = 4;

}


//-----------------------------------------------------

template<typename T>

class ScopedPtr //缺点 不能解决 两个对象之间的拷贝 

{

public:

    ScopedPtr(T* ptr = NULL)

        :_ptr(ptr)

    {}


    ~ScopedPtr()

    {

        if (_ptr)

        {

            cout<<"delete:"<<_ptr<<endl;

            delete _ptr;

        }

    }


    T& operator*()

    {

        return *_ptr;

    }


    T* operator->()

    {

        return _ptr;

    }


    //与AutoPtr相比 简单 粗暴 直接加protected:防止拷贝构造和赋值重载 同时也防止别人在类外实现

protected:

    ScopedPtr(ScopedPtr<T>& sp);

    ScopedPtr<T>& operator=(ScopedPtr<T>& sp);


protected:

    T* _ptr;

};


void TestScopedPtr()

{

    ScopedPtr<int> sp1(new int(1));

   // ScopedPtr<int> sp2(sp1);

}


//------------------------------------------

template<typename T>

class SharedPtr

{

public:

    SharedPtr(T* ptr = NULL)

        :_ptr(ptr)

        ,_pCount(new long(1))

    {}


    ~SharedPtr()

    {

        _Release();

    }


    SharedPtr(const SharedPtr<T>& sp)

        :_ptr(sp._ptr)

        ,_pCount(sp._pCount)

    {

        ++(*_pCount);

    }

/************************************

   SharedPtr<T>& operator=(const SharedPtr<T>& sp)

   {

       // 考虑多种情况

       // 1 sp1 = sp1

       // 2 sp1 = sp2; ==>sp1,sp2管理着同一块内存

       // 3 sp1 = sp3 sp1与sp3 指向的空间不同


       if (_ptr != sp._ptr)//排除1、 2

       {

  _Release();


  _ptr = sp._ptr;

  _pCount = sp._pCount;

  (*_pCount)++;

       }


        return *this;

   }

   ***************************************/


SharedPtr<T>& operator=(SharedPtr<T> sp)//不用引用 不用const

   {

      //现代 写法

  swap(_ptr, sp._ptr);

  swap(_pCount, sp._pCount);


        return *this;

   }

技术分享


   T& operator*()

   {

return *_ptr;

   }


   T* operator->()

   {

return _ptr;

   }


   long UseCount()

   {

return *_pCount;

   }


   T* GetPtr()

   {

return _ptr;

   }



protected:

void _Release()

{

if(--(*_pCount) == 0)

{

delete _ptr;

delete _pCount;

}

}


protected:

    T* _ptr;

    long* _pCount;

};


void TestSharedPtr()

{

    SharedPtr<int> sp1(new int(1));

    SharedPtr<int> sp2(sp1);

    SharedPtr<int> sp3(sp1);


   // int a;

   // const int* p = &a;

   //// int const * p = &a;

   // // error: (*p) = 1; 要是可修改的左值

   // // p = &a;

   //// int * p2 = p; // error  不能从const到非const


   // int * const p3 = &a;

   ////error  p3 = &a;要是可修改的左值

   // *p3 = 5;


cout<<"sp1:"<<sp1.UseCount()<<endl;

cout<<"sp2:"<<sp2.UseCount()<<endl;

cout<<"sp3:"<<sp3.UseCount()<<endl<<endl;


sp1 = sp1;

sp1 = sp2;


cout<<"sp1:"<<sp1.UseCount()<<endl;

cout<<"sp2:"<<sp2.UseCount()<<endl;

cout<<"sp3:"<<sp3.UseCount()<<endl<<endl;


SharedPtr<int> sp4(new int(2));

sp1 = sp4;


cout<<"sp1:"<<sp1.UseCount()<<endl;

cout<<"sp2:"<<sp2.UseCount()<<endl;

cout<<"sp3:"<<sp3.UseCount()<<endl;

cout<<"sp4:"<<sp4.UseCount()<<endl;


}


//-----------------------------------------------------

template<typename T>

class ScopedArray

{

public:

ScopedArray(T* ptr = NULL)

:_ptr(ptr)

{}


~ScopedArray()

{

if (_ptr)

{

delete[] _ptr;

}

}


/*T& operator*()

{

return *_ptr;

}


T* operator->()

{

return _ptr;

}*/

//不需要重载上面两个 用operator[]


T& operator[](size_t index)

{

return _ptr[index];

}

protected:

ScopedArray(const ScopedArray<T>& sp);

ScopedArray<T>& operator=(const ScopedArray<T>& sp);


protected:

T* _ptr;

};


void TestScopedArray()

{

struct V

{

int _v;

};


ScopedArray<V> sa(new V[10]);

sa[0]._v = 1;

sa[2]._v = 11;

}


//-----------------------------test.cpp--

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>

using namespace std;


#include "SmartPtr.h"


//void Test1()

//{

//    int* p = new int(1);

//

//    if (1)

//    {

//        delete p;

//

//        return;

//    }

//    delete p;

//}

//void DoSomething()

//{

//    if (1)

//    {

//        throw 1;

//    }

//}

//

//void Test2()

//{

//    int* p = new int(1);

//    try

//    {

//        DoSomething();

//    }

//    catch(...)

//    {

//        delete p;

//        throw;

//    }

//

//    delete p;

//}

//

//void Test1()

//{

//    int* p = new int(1);

//    AutoPtr<int> ap(p);

//    if (1)

//    {

//       // delete p;

//

//        return;

//    }

//   // delete p;

//}

//void DoSomething()

//{

//    if (1)

//    {

//        throw 1;

//    }

//}

//

//void Test2()

//{

//    int* p = new int(1);

//    AutoPtr<int> ap(p);

//

//    DoSomething();

//    /*try

//    {

//        DoSomething();

//    }

//    catch(...)

//    {

//        delete p;

//        throw;

//    }

//

//    delete p;*/

//}

//

//int main()

//{

//    try

//    {

//        Test1();

//        Test2();

//    }

//    catch(...)

//    {

//        cout<<"未知异常"<<endl;

//    }

//

//    getchar();

//    return 0;

//}





int main()

{

    

    //TestSharedPtr();


TestScopedArray();


getchar();

    return 0;

}


本文出自 “城市猎人” 博客,请务必保留此出处http://alick.blog.51cto.com/10786574/1758966

以上是关于C++ 几种智能指针的简单实现的主要内容,如果未能解决你的问题,请参考以下文章

聊聊 C++ 中的几种智能指针(下)

C++智能指针简单剖析

聊聊 C++ 中的几种智能指针 (上)

C++单线程智能指针实现

模拟实现c++标准库和boost库中的智能指针

C++智能指针原理与实现