c++第23次课(智能指针)__2018.06.08

90%的情况都是在使用无序容器。

函数模板可以不适用<int>它可以进行类型推演。

哈希统计。键、值。

进行哈希映射。大文件的东西分别放到小文件中。

对于服务器来说,磁盘会很大。

在两个文件中查重。

给了不看,和不给一样。

智能指针。

裸指针:直接*访问的指针。就是普通的指针。

例如:int* p=new int;//裸指针

裸指针的缺点:

1.必须手动释放资源。

2.由于程序逻辑的错误,导致释放资源的代码没有被执行到。

3.程序抛出异常,导致没有被调用。

智能指针:智能(不管程序运行发生了什么意外的情况,一定会帮用户释放掉。)

智能指针,开辟内存在栈上开,只要出了栈,资源一定会被释放。是一个类。

自己给智能指针提供*运算符的重载函数,实现类*。

对象调用自己的运算符重载函数。

常对象只能调用常方法。

为什么要给它提供这些运算符重载函数呢?就是为了使只能指针用起来和裸指针一样,就是想用智能指针来替代裸指针呢。

不带引用计数的智能指针。(不能解决对象的浅拷贝问题)(对象的拷贝构造和赋值时会出现问题)

#include <iostream>
using namespace std;

template<typename T>
class CSmartPtr
{
public:
	CSmartPtr(T *ptr = NULL)
		:mptr(ptr){}
	~CSmartPtr(){ delete mptr; }

	T& operator*()
	{
		return *mptr;
	}
	const T& operator*()const
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
	T* operator->()const
	{
		return mptr;
	}
private:
	T *mptr;
};

class A
{
public:
	void func(){ cout << "call A::func" << endl; }
};
int main(int argc, char* argv[])
{
	CSmartPtr<int> ptr1(new int);
	*ptr1 = 30;
	cout << *ptr1 << endl;

	const CSmartPtr<int> ptr2(new int(40));
	cout << *ptr2 << endl;

	CSmartPtr<A> ptr3(new A());
	(*ptr3).func();

	//ptr3.operator->(func());
	//(ptr3.operator->())->func();
	ptr3->func();

	const CSmartPtr<A> ptr4(new A());
	ptr4->func();

	return 0;
}

让指针指向了堆上的资源。

给它提供自定义的拷贝构造函数。(浅拷贝)

智能指针智能的释放资源。

所有的智能指针都需要考虑浅拷贝问题。

#include <memory>//包含的c++中所有的智能指针。

提供了*号运算符的重载函数。

没有提供<<运算符的重载函数。

库中提供的智能指针,会把资源的所有权拿过来,原来的智能指针就置为NULL,全部失效了。

auto_ptr是第一个出现在c++库中的智能指针。

原来智能指针底层的指针都置为空了。

智能指针:带引用计数的智能指针、不带引用计数的智能指针。

堆资源只能用地址来表示。

无序的map。

随手将指针置为NULL是个好习惯。

哈希表虽然快,但也经不起多次遍历。

不希望外部用户看到的方法就声明成私有方法,只给内部提供服务。

静态成员方法要在类外初始化。

带引用计数的智能指针。

#include <iostream>
#include <memory>    // 这个头文件中,包含了C++库所有的智能指针
#include <unordered_map>
using namespace std;

/*
专门用来统计资源的引用计数  void*  int

*/
class ReferenceCount
{
public:
	//给ptr指向的资源增加引用计数
	void incRef(void *ptr)
	{
		refMap[ptr]++;
	}
	//给ptr指向的资源减少引用计数
	int decRef(void *ptr)
	{
		unordered_map<void*, int>::iterator it = refMap.find(ptr);
		if (it == refMap.end())
		{
			return 0;
		}
		else
		{
			if (it->second > 1)
			{
				--(it->second);
				return it->second;
			}
			else
			{
				return 0;
			}
		}

	}
private:
	//map的key表示资源地址, value表示资源的引用计数
	unordered_map<void*, int> refMap;
};


template<typename T>
class CSmartPtr
{
public:
	CSmartPtr(T *ptr = NULL)
		:mptr(ptr)
	{
		if (mptr != NULL)
		{
			incRef();
		}
	}
	CSmartPtr(const CSmartPtr<T> &src)
		:mptr(src.mptr)
	{
		if (mptr != NULL)
		{
			incRef();
		}
	}
	CSmartPtr<T>& operator=(const CSmartPtr<T> &src)
	{
		if (this == &src)
			return *this;

		if (decRef() == 0)
		{
			delete mptr;
			mptr = NULL;
		}

		mptr = src.mptr;
		if (mptr != NULL)
		{
			incRef();
		}
		return *this;
	}
	~CSmartPtr()
	{
		if (decRef() == 0)
		{
			delete mptr;
			mptr = NULL;
		}
	}

	T& operator*()
	{
		return *mptr;
	}
	const T& operator*()const
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
	T* operator->()const
	{
		return mptr;
	}
private:
	T *mptr;
	//专门供智能指针,查看当前它所引用的资源的引用计数
	static ReferenceCount refCnt;

	void incRef() { refCnt.incRef(mptr); }
	int decRef() { return refCnt.decRef(mptr); }
};

template<typename T>
ReferenceCount CSmartPtr<T>::refCnt;

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

int main(int argc, char* argv[])
{
	CSmartPtr<int> ptr1(new int);
	*ptr1 = 30;
	cout << *ptr1 << endl;

	CSmartPtr<int> ptr2(ptr1);
}

线程安全的智能指针。

1.++、--都不是线程安全的。

2.容器的插入删除本身就不是线程安全的。

类的前置声明:class A ;

智能指针(可以直接改变引用计数)是不能放在堆上的。

强智能指针循环/交叉引用时造成资源无法释放。

怎么解决?=》弱智能指针。

一个资源都有一个引用计数。

弱智能指针,无法直接接触引用计数表。它通过强智能指针感受引用计数。

弱智能指针只能观察引用计数。而不能直接操作引用计数。

week_ptr<B> _ptrb;

定义资源的地方采用强智能指针,要和资源挂上钩。使用智能指针的地方全部使用弱智能指针。

share_ptr(强智能指针)和week_ptr(弱智能指针)。(库中提供的)

A的析构导致了A的成员对象的析构。

智能指针是单独的一块,非常重要的东西。

在加加减减的时候没有进行任何的线程安全处理。

咱们写的智能指针没有提供线程安全的处理。

share_ptr(强智能指针)和week_ptr(弱智能指针)。提供了线程安全的处理。

弱智能指针之所以没有直接指向资源,不能改变引用计数,是因为弱智能指针根本没有提供指向运算符的重载的函数。

指向对象的弱智能指针不能引用对象的成员方法。

弱智能指针把自己提升成强智能指针(lock)。在提升前,会先观察强智能指针的引用计数,如果已经为0则提升失败。

提升成功后资源的引用计数也会加一,防止强智能指针将资源析构掉。

单线程中程序是串行执行的。多线程中任务是并行执行的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值