SmartPointer_智能指针

动态内存

C++中程序用来存储动态分配(dynamically allocate)的对象——即那些在程序运行时分配的对象。

动态内存的生存期由程序控制,也就是当动态对象不再使用时,我们必须显示的销毁它们。

But众所周知(王小波句式),正确的管理动态内存是非常棘手的。如果忘了释放内存,就会导致内存泄漏;如果在还有指针引用内存时就去释放那块内存,那么那个指针就会变为一个引用非法内存的指针。thorny problem!

智能指针原理

So, 为了更容易更安全的使用动态内存,新的标准库提供了智能指针(smart pointer)类型来管理动态对象。

智能指针的行为类似常规指针,区别是它负责自动释放所指向的对象。

那么smart pointer是如何做到自动释放内存的呢?

其实,智能指针是一个类类型,假如给它起个类名叫SmartPtr吧。在这个SmartPtr类中,有一个private成员变量,这个变量是另外一种类类型的指针(就是说它是一个指针,指向一个类),然后通过这个指针来动态创建类的对象。

比如,这里创建了SmartPtr类和Animal类,SmartPtr中的成员变量ptr_为Animal类的一个指针。

代码如下:

#ifndef SMARTPTR
#define SMARTPTR 

#include <iostream>

//禁用赋值与复制
#define DISALLOW_COPY_AND_ASSIGN(TypeName)     TypeName(const TypeName&);     void operator=(const TypeName&)

class Animal
{
    public:

        Animal()
        {
            std::cout << "construct......." << std::endl;
        }

        ~Animal()
        {
            std::cout << "destruct ... " << std::endl;
        }
        void run()
        {
            std::cout << "running......." << std::endl;
        }
};

class SmartPtr
{
    public:
        //SmartPtr针对的是heap上的对象
        SmartPtr(Animal *ptr);
        ~SmartPtr();

        Animal &operator*();
        const Animal &operator*() const;

        Animal *operator->(); //重载SmartPtr这个类的->
        const Animal *operator->() const;
    private:
        DISALLOW_COPY_AND_ASSIGN(SmartPtr);
        Animal *ptr_;
};

#endif  /*SMARTPTR*/

SmartPtr::SmartPtr(Animal *ptr)
    :ptr_(ptr)
{
}

SmartPtr::~SmartPtr()
{
    delete ptr_; //SmartPtr析构时释放指向Animal类的指针,从而释放内存
}

Animal &SmartPtr::operator*()
{
    return *ptr_;
}
//const 版本
const Animal &SmartPtr::operator*() const
{
    return *ptr_;
}

Animal *SmartPtr::operator->()
{
    return ptr_;
}

//const版本
const Animal *SmartPtr::operator->() const
{
    return ptr_;
}

然后我们编写一个异常处理函数来测试一下:

#include <stdexcept>
#include "SmartPtr.hpp"
using namespace std;

int main(int argc, const char *argv[])
{
    try{
        //这里的ptr离开try时一定会被销毁
        //从而导致Animal对象一定会被析构
        SmartPtr ptr(new Animal);
        throw runtime_error("error");

    }catch(runtime_error &e)
    {
        cout << e.what() << endl;
		/*
		construct...
		destruct...
		error
		*/
    }
    return 0;
}

这里补充一点:在异常处理函数中,如果在栈展开过程中退出了某个块(执行到throw语句),编译器将会负责确保在这个块中的对象能被正确的销毁。如果某个局部对象的类型是类类型,则该对象的析构函数将会被自动调用。

所以,上面程序中当执行到throw语句时,直接跳到catch中继续运行。那么原来try中的东东会确保被销毁,也就是编译器自动会去调用ptr这个对象的析构函数,从而执行了delete ptr_, 所以存储Animal对象的内存就被自动释放了。

一句话,智能指针利用了栈对象的生存期,将资源的获取放在构造函数里面,资源的释放放在析构函数里面,从而保证了资源一定会被正确释放。

最后,这也就是C++中的RAII(Resource Acquirement Is Initialization)

RAII要求,资源的有效期与持有资源的对象的生命期严格绑定,即由对象的构造函数完成资源的分配(获取),同时由析构函数完成资源的释放。在这种要求下,只要对象能正确地析构,就不会出现资源泄露问题。

时间: 2024-11-10 13:03:33

SmartPointer_智能指针的相关文章

智能指针的原理和简单实现

什么是智能指针? 智能指针实质上是一个类,定义一个类来封装资源的分配和释放.这个类的构造函数中传入一个指针,完成资源的分配和初始化.在析构函数中释放传入的该指针,完成资源的释放. 为什么要用智能指针? 智能指针就是智能,自动化的管理指针所指向的动态资源. 例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露. // case1 void Test2() {  int* p1 = new int(2);  bool isEnd = true;  //...  if (isEnd)  

实战c++中的智能指针unique_ptr系列-- 使用std::unique_ptr代替new operator(错误:‘unique_ptr’ is not a member of ‘std’)

写了很多篇关于vector的博客,其实vector很便捷,也很简单.但是很多易错的问题都是vector中的元素为智能指针所引起的.所以决定开始写一写关于智能指针的故事,尤其是unique_ptr指针的故事. 这是个开始,就让我们使用std::unique_ptr代替new operator吧! 还是用程序说话: #include<iostream> int main() { while (true) int *x = new int; } 看下任务管理器中的内存: 此时使用智能指针unique

C++智能指针简单剖析

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

boost智能指针使用

#include <iostream> #include <tr1/memory> #include <boost/scoped_ptr.hpp> //scoped_ptr还不属于tr1 #include <boost/scoped_array.hpp> //scored_array也不属于tr1 #include <boost/shared_array.hpp> //shared_array也不属于tr1 class CTest { publi

webkit智能指针 - RefPtr, PassRefPtr

历史 2005年之前,Webkit中很多对象都采用引用计数的方式.它们通过继承RefCounted]类模板来实现这种模式.RefCounted主要是实现了ref()和deref()两个函数.在需要引用对象时要调用ref()增加引用计数,在不再需要对象时,要调用deref()函数减少引用计数.ref()和deref()需要成对出现.这和使用new/delete一样,多调用.少调用.没调用的问题总是时有发生.如果能由编译器自动完成ref, deref的调用,C/C++编程的bug至少也可以减少一半以

智能指针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

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

C++之智能指针20170920

/******************************************************************************************************************/ 一.C++智能指针_自己实现智能指针 1.使用局部变量结合new的方式,防止new导致的内存泄漏 class sp { private: Person *p; public: sp() : p(0) {}//表明sp的构造函数 继承person的无参构造函数 sp(

智能指针简介

智能指针用于解决常规指针所带来的内存泄露.重复释放.野指针等内存问题.智能指针基于这样的事实得以发挥作用:定义在栈中的智能指针,当超出其作用域时,会自动调用它的析构函数,从而可以释放其关联的内存资源. 之前C++标准库中定义的智能指针std::auto_ptr<T>,因其设计存在缺陷,所以已不再推荐使用.C++11引入了新的智能指针:unique_ptr.shared_ptr和weak_ptr. 一:unique_ptr unique_ptr类似于auto_ptr.两个unique_ptr实例