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;

}

时间: 2024-11-13 00:02:52

C++ 几种智能指针的简单实现的相关文章

智能指针的简单总结

1. 智能指针背后的设计思想 我们先来看一个简单的例子: void remodel(std::string & str) { std::string * ps = new std::string(str); ... if (weird_thing()) throw exception(); str = *ps; delete ps; return; } 当出现异常时(weird_thing()返回true),delete将不被执行,因此将导致内存泄露. 如何避免这种问题?有人会说,这还不简单,直

四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr

stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针的使用总结 (1)auto_ptr 主要用于解决资源自动释放的问题.防止用户忘记delete掉new申请的内存空间.使用auto_ptr会在离开变量的作用域之后直接调用析构函数进行资源释放. void Function() { auto_ptr<Obj> ptr(new Obj(20)); ... if (error occur) throw exception... } 但是,这是一种被c++1

智能指针的简单剖析和实现

在C语言中我们用指针来进行内存管理,这也是C语言的强大之处.然而,也正是指针的存在使得C语言变得令人懊恼,内存泄漏.垂悬指针等等问题.强大的C++则采用智能指针(Smart_Ptr)来处理这个问题. 好了,什么是智能指针呢?智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象.这样以防止内存泄漏. 智能指针都有哪些种类呢? 通过上述表格可以看出有如此多的智能指针,C11标准库已经引进unique_ptr/shared_ptr/weak_ptr供我们使用. 下面来简单谈谈这些指针的原

C++智能指针及其简单实现

本将主要介绍智能指针shared_ptr和unique_ptr,并简单实现基于引用计数的智能指针. 自C++11起,C++标准提供两大类型的智能指针: 1. Class shared_ptr实现共享式拥有(shared ownership)概念.多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用(reference)被销毁”时候释放.为了在结构复杂的情境中执行上述工作,标准库提供了weak_ptr.bad_weak_ptr和enable_shared_from_this等辅助类.

C++几种智能指针之间的比较

这些智能指针在设计的时候,一个关键的问题就是所有权的控制.如果把指针所指向的对象比作电视机的话,那么指针就是观众.第一个人需要看电视的时候需要打开它,没人看的时候就要保证把电视关掉. 对于std::auto_ptr,boost::shared_ptr和scoped_ptr,情况如下: 1. std::auto_ptr:auto_ptr这个种族很有趣,每次只让一个人看电视,大家可以换着看,由最后那个不想看的人关掉.当把一个auto_ptr赋值给另一个时,就好比换一个人看电视似的.总之,电视只能一个

智能指针的简单实现

智能指针:动态的管理开辟的内存,防止人为的内存泄漏. SharedPtr的实现: 原理:使用引用计数的原理使多个对象可以指向一块空间. #define  _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; template <class T> class SharedPtr { public: SharedPtr() :_count(new int(1)), _ptr(NULL) {} SharedPtr(

3种智能指针

出现智能指针的原因 用智能指针,把申请内存的工作都在接口内部实现并加以限制,把释放内存的工作交给智能指针. 常见的智能指针 1.你知道智能指针吗?智能指针的原理.     2.常用的智能指针.     3.智能指针的实现. 1答案:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针.智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放, 2, 最常用的智能指针: 1)std::auto_ptr,有很多问题. 不支持复制(拷贝构造函数)和赋值(operat

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

智能指针的用处:在c++中,使用普通指针容易造成堆内存的泄露问题,即程序员会忘记释放,以及二次释放,程序发生异常时内存泄漏等问题,而使用智能指针可以更好的管理堆内存.注意,在这里智能指针是一个类而非真正的指针,只是对一个真正的指针进行包装,代理原指针.通过操作符的重载,可以让智能指针和真正的指针有类似的操作. 如何实现:在智能指针析构函数当中,可以对代理的原指针进行delete以及赋空指针等操作,智能指针销毁时,自动调用析构函数,省去了程序员自己管理指针的操作.当多个智能指针代理同一个指针时,我

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录