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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++primer第十二章读书笔记---动态内存与智能指针相关的知识,希望对你有一定的参考价值。

    目前为止我们使用过的静态内存,栈内存和内存池,静态内存用来保存局部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;
}


以上是关于C++primer第十二章读书笔记---动态内存与智能指针的主要内容,如果未能解决你的问题,请参考以下文章

《C++Primer(第5版)》第十二章笔记

C++Primer 第十二章

读书共享 Primer Plus C-part 9

C Primer Plus(第六版)第十二章 编程练习答案

第十二章 动态内存与智能指针

读书笔记,《反脆弱》,第十二章,泰勒斯的甜葡萄