您的位置:首页 > 编程语言 > C语言/C++

C++primer第十二章读书笔记---动态内存与智能指针

2016-04-01 15:51 459 查看
目前为止我们使用过的静态内存,栈内存和内存池,静态内存用来保存局部static对象、类static成员,以及定义在任何函数之外的成员。栈内存用来保存定义在函数内部的非static成员,分配在静态 内存或栈内存中的对象由编译器自动创建或销毁,对于栈对象仅在其定义的程序块运行时才有效,static对象在程序运行之前分配,程序结束时销毁。除了静态内存和栈内存外,每个程序还拥有一个内存池(堆)在堆上分配动态对象,当动态对象不再使用时,我们必须显示的销毁它。
(一)、动态内存与智能指针
new在动态内存中为对象开辟空间,并返回指向该对象的指针;delete接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
动态内存的使用很容易出现问题,有时候我们会忘记释放它,在这种情况下就会造成内存泄露,泄露的内存越堆积越多最终编译器无法为程序分配新的内存,系统崩溃。有时在尚有指针引用的内存的情况下我们就释放它,这种情况下会产生引用非法内存的指针。
说了这么多,让人感觉动态内存挺矫情的,不过矫情有矫情的治法,在这种情况下智能指针就能够很好地解决这种状况。智能指针行为类似常规指针,最最重要的区别就是它是一个负责任的指针,能够中自动释放所指向的对象。
(1)sharedptr--允许多个指针指向同一个对象
(2)scopedptr--守卫智能指针,简单粗暴
智能指针也是模板,因此当我们创建一个智能指针时必须提供额外的信息---智能指针指向的类型
在尖括号内给出类型,之后就是定义这种智能指针的名字:
sharedptr<string> p1   //sharedptr,可以指向string
sharedptr<list<int>> p2 //sharedptr,可以指向int的List链表
默认初始化的智能指针中保存着一个空指针,智能指针的使用方式与普通指针类似,解引用一个智能指针返回指向它的对象,如果在一个条件判断中使用智能指针,效果就是检测它是否为空。
(二)sharedptr自动销毁所管理的对象
当指向对象的最后一个sharedptr 被销毁时,sharedptr会自动销毁此对象,它通过析构函数完成销毁工作,析构函数一般用来释放对象所分配的资源。除此之外,sharedptr 还会自动释放相关联的内存。它是通过引用计数的方式来管理内存的,
shardptr<T>P(q)
p是sharedptr的拷贝,此操作会递增q中的引用计数,q中的指针必须转化为T*
p=q
p和q都是sharedptr,所保存的指针必须能够相互转化,此操作会递减p的引用计数,递增q的引用计数;若p的引用计数变为0,则将其管理的原来内存释放;

有关这两个指针的实现具体看后边的源代码哦
#include<iostream>
using namespace std;
template<typename T>
//1
class Autoptr
{
public:
//构造函数
Autoptr(T* ptr):_ptr(ptr)
{}
//析构函数
~Autoptr()
{
if(_ptr)
{
cout<<"delete"<<_ptr<<endl;
delete _ptr;
_ptr=NULL;
}
}
//拷贝构造函数
Autoptr(Autoptr<T> &ap):_ptr(ap._ptr)
{
ap._ptr=NULL;
}
//赋值运算符符重载
Autoptr<T>& operator=(Autoptr<T> &ap)
{
if(this!=&ap)
{
delete _ptr;
_ptr=ap._ptr;
ap._ptr=NULL;
}
return *this;
}
//->运算符重载
T* operator->()
{
return _ptr;
}
//*运算符重载
T&operator*()
{
return *_ptr;
}
private:
T* _ptr;
};

//
template <typename T>
class Scopedptr
{
public:
//
Scopedptr(T* ptr):_ptr(ptr)
{}
//
~Scopedptr()
{
if(_ptr)
{
cout<<"delete"<<_ptr<<endl;
delete _ptr;
}

}
//->运算符重载
T* operator->()
{
return _ptr;
}
//*运算符重载
T&operator*()
{
return *_ptr;
}
//防拷贝
//只声明不实现
//	(1)声明为保护或私有成员防止函数在外边被篡改
//	(2)防止调用默认的函数
protected:
Scopedptr(Scopedptr<T> &sp);
Scopedptr<T>&operator=(Scopedptr<T>& sp);
protected:
T *_ptr;
};

template <typename T>
class Shardptr
{
public:
//构造函数
Shardptr(T *ptr)
:_ptr(ptr)
,_pcount(new long(1))
{

}
//析构函数
~Shardptr()
{
if(--(*_pcount)==0)
{
delete _ptr;
delete _pcount;
}
}
//拷贝构造函数
Shardptr(Shardptr<T>& sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount)
{
++(*_pcount);
}
//赋值运算符重载
Shardptr<T>& operator=(const Shardptr<T>& sp)
{
//sp1=sp1
//sp1=sp2
//sp1=sp3
if(this_ptr!=sp._ptr)
{
if(--(*_pcount)==0)
{
delete _ptr;
delete _pcount;
}
_ptr=sp._ptr;
_pcount=sp._count;
++(*_pcount);
}
}
//
T& operator*()
{
return *_ptr;
}
//
T* operator->()
{
return _ptr;
}
//
long Usecount()
{
return *_pcount;
}
private:
T*_ptr;
long*_pcount;
};

//
template<typename>
class ScopedArray
{
pubilc:
ScopedArray(T* ptr):_ptr(ptr)
{}
~ScopedArray()
{
if(_ptr)
{
delete [] _ptr;
}
}
//
T& oprator[](size_t index)
{
return _ptr[index];
}
protected:
ScopedArray(const ScopedArray<T>&sp);
ScopedArray(const ScoopedArray<T>&sp);
private:
T * _ptr;
};
void test1()
{
//int *p=new int(1);
//Autoptr<int>ap(p);
Autoptr<int>ap1(new int(1));
Autoptr<int>ap2(ap1);
Autoptr<int>ap3(new int(2));
ap3=ap2;
*ap3=10;//ap3.operator*(&ap3);
/*Autoptr<int>ap4(new A);
ap4->_a=10;*/
cout<<ap3.operator*()<<endl;
}
void test2()
{
//Scopedptr<int>sp1(new int(2));
}

void TestShardptr()
{
Shardptr<int> sp1(new int(1));
Shardptr<int>sp2(sp1);
*sp2=20;
Shardptr<int>sp3(new int(3));
/*sp3=sp2;*/
cout<<"sp:"<<sp1.Usecount()<<endl;
cout<<"sp2:"<<*sp2<<endl;
}
void TestScopedArray()
{
ScopedArray<A> sa(new A[10]);

}
int main()
{
TestShardptr();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息