C++智能指针管理类

1.程序员明确的进行内存释放

对于c++程序员,最头脑的莫过于对动态分配的内存进行管理了。c++在堆上分配的内存,需要程序员负责对分配的内存进行释放。但有时内存的释放看起来并不件很轻松的事,如下程序

void func()
{
    int *p = new int(0);
    if(一些判断)
    {
        return;
    }
    p = new int(1);
    delete p;
}

这个函数没有任何意义,只为说明问题。func函数至少有三处问题。1.一旦if的判断条件成立,就会立马执行返回语句。此时p所指向的内存将无法释放(这个新手一般都会犯的错误)。2. p = new int(1);语句,没有将原来分配在堆上的内存释放,造成原来那块内存永远不可能释放直到程序结束。3.这个问题并不是那么明显,假设func()函数的代码很长。

void func()
{
    int *p = new int(0);
    ...
    delete p;
}

在int *p = new int(0)和delete p之间有大量代码,而这中间的代码可能有代码已经执行过delete p,并且没有把p置0。此时p为悬挂指针。后面再执行delete p就会造成运行时错误。

2.一个类似于boost shared_ptr的智能指针管理类

下面是参照c++ primer及effective c++自己写的一个智能指针管理类。使用SmartPtr,就不再需要关心内存的释放问题了。

#ifndef SMARTPTR_INCLUDE_H
#define SMARTPTR_INCLUDE_H
#include <iostream>
using namespace std;
namespace commutil
{
    template<typename T>
    class SmartPtr
    {
    public:
        SmartPtr(T *p = 0);
        SmartPtr(const SmartPtr &);
        SmartPtr &operator=(const SmartPtr &);
        ~SmartPtr();
        T &operator *();
        T *operator ->();
    private:
        void decreaseRef();
        T *m_p;
        int *m_useCnt;
    };
    template<typename T>
    SmartPtr<T>::SmartPtr(T *p=0):m_p(p)
    {
        //调用此构造函数时,默认引用数为1
        m_useCnt = new int(1);
    }

    template<typename T>
    SmartPtr<T>::SmartPtr(const SmartPtr &rhs)
    {
        //使用复制构造函数,创建新的对象,引用数加1
        this->m_p = rhs.m_p;
        this->m_useCnt = rhs.m_useCnt;
        (*m_useCnt)++;
    }

    template<typename T>
    SmartPtr<T>::~SmartPtr()
    {
        decreaseRef();
    }

    template<typename T>
    void SmartPtr<T>::decreaseRef()
    {
        if(--(*m_useCnt)==0)
        {//当引用数为0时,释放heap内存
            delete m_useCnt;
            delete m_p;
        }
    }

    template<typename T>
    T &SmartPtr<T>::operator *()
    {
        //重载解引用符
        return *m_p;
    }

    template<typename T>
    T *SmartPtr<T>::operator ->()
    {
        //重载 ->运算符,返回真实的对象指针
        return m_p;
    }

    template<typename T>
    SmartPtr<T> &SmartPtr<T>::operator=(const SmartPtr &anotherPtr)
    {
        if(this==&anotherPtr)
        {//防止自赋值
            return *this;
        }
        //使用赋值运算符,原来所指对象的引用数减1。
        decreaseRef();
        m_p = anotherPtr.m_p;
        m_useCnt = anotherPtr.m_useCnt;
        ++*m_useCnt;//指向新的对象,所指对象引用数加1
        return *this;
    }
}
#endif

3.使用SmartPtr的案例分析

3.1第一个SmartPtr的实例

void func()
{
    SmartPtr<int> autoPtr(new int(1));
}

在func中,定义了SmartPtr的一个对象autoPtr,并用new int(1)在堆上分配一块内存,将分配的内存首地址传给SmartPtr的构造函数。此时autoPtr的m_useCnt的值为1。当func执行完成时,autoPtr对象超出其作用域,调用autoPtr的析构函数。在析构函数中调用私有的decreaseRef()函数,在decreaseRef()中将autoPtr的m_useCnt所内存值减1;此时m_useCnt所指内存值为0,执行delete m_useCnt;delete m_p;。至此在创建autoPtr对象时动态分配的内存被释放。

3.2带有return语句的SmartPtr

void func()
{
    SmartPtr<int> autoPtr(new int(1));
    if(判断条件)
    {
        return;
    }
}

func()函数中的if判断条件成立时,执行return;语句后,autoPtr超出其作用范围,内存释放。分析见3.1

3.3 SmartPtr对象管理新的SmartPtr对象

    SmartPtr<int> autoPtr1(new int(0));
    SmartPtr<int> autoPtr2(new int(1));
    autoPtr1 = autoPtr2;

执行autoPtr1 = autoPtr2,由于SmartPtr类重载了赋值运算符。实际执行的是SmartPtr的operator=()函数,在上面这个赋值语句中,先autoPtr1的m_useCnt所指内存值减1。此时m_useCnt所指内存值变为0,执行m_p所指内存释放。使用SmartPtr解决了1中所提的第二个问题。并且所有内存管理与释放工作都由SmartPtr进行,程序员不需要再关心什么时候进行内存释放。

3.4SmartPtr共享对象资源

与auto_ptr不同,SmartPtr使用引用计数机制保证多个SmartPtr对象可以管理同一个对象资源

void func()
{
    SmartPtr<int> autoPtr1(new int(0));
    SmartPtr<int> autoPtr2(autoPtr1);
}

执行SmartPtr autoPtr2(autoPtr1)调用SmartPtr的拷贝构造函数,在拷贝构造函数中将autoPtr2的m_useCnt及m_p分别指向autoPtr1所指向的内存,再将m_useCnt的引用数加1。func()函数结束时,两次调用SmartPtr的析构函数,两次析构函数后引用数为0,删除m_useCnt,m_p所指内存。

3.5SmartPtr访问类成员函数

class A
{
public:
    void print()
    {
        cout<<"A"<<endl;
    }
};

void func()
{
    A *obj = new A();
    obj->print();
    delete obj;
}

SmartPtr重载了->运算符,可以将SmartPtr对象像指针一样访问成员函数。

void func()
{
    SmartPtr<A> autoPtr(new A());
    autoPtr->print();
}

4.小结

SmartPtr类实现了内存对象”自管理”,使用SmartPtr程序员不再需要关心动态内存的释放问题。与shared_ptr不同,SmartPtr类只能管理指针类型的资源,并且SmartPtr不支持自定义的资源释放函数。

时间: 2024-10-28 01:41:47

C++智能指针管理类的相关文章

C++_智能指针模板类

智能指针是行为类似于指针的类对象,但这种对象还有其他功能. 本节介绍三个可帮助管理动态内存分配的智能指针模板(auto_ptr.unique_ptr和shared_ptr). void remodel(std:string & str) { std::string * ps = new std::string(str); ... str = ps; return; } 这段代码有缺陷,每当调用时,该函数都分配堆中的内存,但从不回收,从而导致内存泄漏: 但是有解决之道——在return语句前添加下

C++智能指针模板类复习

//C++智能指针模板类复习 #include<iostream> #include<memory> using namespace std; //智能指针用于确保程序不存在内存和资源泄漏且是异常安全的. //C++98中提供了auto_ptr,C++11摒弃了auto_ptr,并提出了unique_ptr .shared_ptr.weak_ptr void show1() { int* p = new int(4); cout << *p << endl;

《C++ Primer Plus》16.2 智能指针模板类

智能指针是行为类似于指针的类对象,单这种对象还有其他功能.本节介绍三个可帮助管理动态内存分配的智能指针类.先来看看需要哪些功能以及这些功能是如何实现的.请看下面的函数:void remodel(std::string & str){    std::string * ps = new std::string(str);    ...    str = ps;    return;}您可能发现了其中的缺陷.每当调用时,该函数都分配堆中的内存,单从不回收,从而导致内存泄漏.您肯呢哥也知道解决之道——

智能指针模版类

有三个智能指针,auto_ptr(弃用).unique_ptr.shared_ptr. 智能指针可以自动跟踪动态内存,在其过期时自动释放. 一.shared_ptr 用于new创建的对象,而不适用于new[]创建的对象, 用于多个指针共享一个地址的情况. #include<memory> std::shared_ptr<int> int_ptr=new int; //std::shared_ptr<int> int_ptr(new int); 二.unique_ptr

C/C++——跟我重写智能指针auto_ptr模版类

第一次使用auto_ptr的时候感觉很好用,但是对内部原理根本不懂,心里不知道这东西到底是个什么东东,总是感觉这东东比较陌生.今天有时间来简单实现一下该类模版auto_ptr,实现了该模版类的主要功能,可以让大家了解一下这个东东内部到底是个什么情况. 栈对象和堆对象的区别: 首先,看一下两种类对象的区别,一个是在栈上分配空间,另一个是在堆上分配空间. 如果看到这里,你不清楚堆和栈的区别.那我也不解释了,自行Google..(如果你想baidu也不拦你) 1.先测试栈上分配的对象 #include

C++中智能指针的模板类

在C++中,智能指针是一个非常重要的概念.因为C++的类动态分配的对象不能自动释放掉,需手动调用new运算符.当程序员大意时,或程序发生异常时,或许就会发生没有手动释放内存而造成内存泄露. 智能指针的定义:就是在一个类中,存在一个指向另一个类对象的指针,并通过对指针运算符(比如:->,*)的重载,就可以实现利用当前类的对象通过指针运算符来操纵另一个类的成员(就像另一个类的指针操作一样),并且,在析构函数中定义了delete操作,借助于变量的作用域,能够实现类对象空间的自动释放. 在C++ 11中

智能指针tr1::shared_ptr、boost::shared_ptr使用

对于tr1::shared_ptr在安装vs同时会自带安装,但是版本较低的不存在.而boost作为tr1的实现品,包含 "Algorithms Broken Compiler Workarounds Concurrent Programming Containers Correctness and Testing Data Structures Domain Specific Function Objects and Higher-order Programming Generic Progra

智能指针

RAII(Resource Acquisition Is Initialization) 资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放. ------------------------------------------------------------------------------------------- 为什么要有智能指针呢? 智能指针的存在是为了防止我们在大型项目中忘记释放空间而导

智能指针 与 oc中的指针

智能指针 与 oc中的指针 智能指针的原理及实现 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副