您的位置:首页 > 其它

文章标题

2016-09-03 13:15 267 查看
C++智能指针部分指针的实现

由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见。


用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法。包括:std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、boost::shared_array、boost::weak_ptr、boost:: intrusive_ptr。你可能会想,如此多的智能指针就为了解决new、delete匹配问题

从而言之:

对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。

举个例子:void fun()

{

int *p=new int(1);

if(1)

{

return;

}

delete p;//会存在内存泄漏的问题,返回后才释放

}

void fun()

{//….代码

if(1)

{

throw 1;

}

//….

}

void test2()

{

int *p=new int (10);

fun();//fun函数内部存在抛出异常,

//抛出异常后直接进入mian函数,内存泄漏

//处理

try

{

fun();

}

catch(…)

{

delete p;

throw;

}

}

int main()

{

try

{

}
catch(...)
{
cout<<"未知异常"<<endl;
}

return 0;


}

如果在1f判断中我们忘记delete p1 ,直接return,那么这块内存就没有释放,很容易造成内存泄露。

所以我们需要使用智能指针来管理动态对象。

所谓智能指针就是智能/自动化的管理指针所指向的动态资源的释放。

STL–auto_ptr

Boost库的智能指针(ps:新的C++11标准中已经引入了

unique_ptr/shared_ptr/weak_ptr)

下面我们分别来看一下这几个智能指针:

1) scoped_ptr:

这是比较简单的一种智能指针,正如其名字所述,

scoped_ptr所指向的对象在作用域之外会自动得到析构,scoped_ptr是non-copyable的,也就是说你不能去尝试复制一个scoped_ptr的内容到另外一个scoped_ptr中,这也是为了防止错误的多次析构同一个指针所指向的对象。顾名思义,守卫的指针,思想就是防拷贝,在大多时候用不到拷贝构造和赋值运算符重载,那么我们做的就是写出构造函数和析构函数,拷贝构造和赋值运算符重载只声明不定义。
这里写代码片


template

class ScopePtr//不允许拷贝构造、赋值

{

public:

ScopedPtr*(T*)

:_ptr(ptr)

{}

~ScopedPtr()

{

if(_ptr != NULL)

{

delete _ptr;

_ptr = =NULL;

}

}

T& operator*()

{

return *_ptr;

}

T*GetPtr()

{

return _ptr;

}

protected:

ScopedPtr(const ScopedPtr& p);

ScopedPtr& operator = (const ScopedPtr& p);

private:

T*_ptr;

};

void TestScopedPtr()

{

boost::ScopedPtr sp1(new int(1));

boost::scopedPtr sp2(sp1);

ScopedPtr p3(new int(3));

p3 = p1;

}

2) shared_ptr:

shared_ptr是一个最像指针的”智能指针”.

shared_ptr与scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针,可以被自由的拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才能删除被包装的动态分配的对象。shared_ptr也可以安全地放到标准容器中,并弥补了auto_ptr因为转移语义而不能把指针做为STL容器元素的缺陷。

下面我们来实现以下这个智能指针。

`template

class SharedPtr

{

public:

SharedPtr(T*ptr)

:_ptr(ptr)

,_pcount(new int(1))

{}

~SharedPtr()

{

if(_ptr)

{

if(–*pconut==0)

{

delete _ptr;

delete _pconut;

_ptr=NULL;

_pcount=NULL;

}

_ptr=NULL;

}

}

SharedPtr(const SharedPtr&sp)

{

_ptr=sp._ptr;

_pconut=sp._pconut;

++(*_pconut);

}

SharedPtr&operator=(const SharedPtr&sp)

{

if(_ptr!=sp._ptr)

{

if(–*_pconut==0)

{

delete _ptr;

delete _pcount;

}

_ptr=sp._ptr;

_pcount=sp._pcount;

++(*_pcount);

}

return *this;

}

private:

T*_ptr;

int *_pcount;

};

void TesSharedPtr()

{

SharedPtr sp1(new int(1) );

SharedPtr sp2(sp1);

sp1=sp1;

sp2=sp1;

SharedPtr sp3(new int (3));

sp3=sp1;

}这里写代码片

2) auto_ptr:

auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放。即使发生异常,通过异常的栈展开过程也能将动态内存释放。auto_ptr不支持new 数组。

但是它有缺陷,STL容器在分配内存的时候,必须要能够拷贝构造容器的元素。而且拷贝构造的时候,不能修改原来元素的值。而auto_ptr在拷贝构造的时候,一定会修改元素的值。所以STL元素不能使用auto_ptr。

所以最好不要使用。`

class AutoPtr

{public:

AutoPtr(T*ptr)

:_ptr(ptr)

{

cout<<”creat”<<_ptr<
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: