【C++11】包装器,智能指针

当面对下面场景时,发现count变量作为静态变量,但是有三个地址,并且count的计数都是1,无法做到每调用一个函数对象就使count++,用来统计调用函数的个数,因为每一组不同的模板参数,都会生成一份独立的函数实例。怎么简化调用接口,并且实现count公用同一块空间?

一.包装器

概念

  • function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。
  • 可以把不同的函数其实例化为一个类型,或者把可调用对象存储到容器中
  • function可以对仿函数,函数指针,lambda进行包装
  • 使用:function<return_val(parameter)>

情景1:

  • 使用包装器包装后,只实例化一份count
  • 另外发现f1和f2的类型都相同,只有在同一个类型下static变量才会定义一份,所以共用一个变量

情景2:

逆波兰表达式求值


std::bind使用

std::bind函数,像函数包装器,是一个函数模板,接收一个可调用对象,生成一个新的可调用对象来"适应"源对象的参数列表。可以实现函数传递参数顺序调整

  • 利用下面标定参数列表的位置:

场景1:

场景2:

情景3:

  • 类内静态成员函数,bind时不需要加this指针
  • 类内非静态成员函数 ,bind时第一个参数添加实例化对象的地址 (使用&),或者传入匿名对象
  • binder类重载了operator()

说明

  • function的和bind底层都是仿函数,bind重载了operator(),通过指针或者对象调用函数,绑定成员函数时,传对象的地址

智能指针

需要的理由

  • 于是在catch到异常时delete,没有catch时delete。可是这样繁杂,于是有了智能指针
  • throw;的作用 :重新抛出当前捕获的异常对象,继续抛给调用栈的上一层,这样保证没有吞掉异常,错误信息被上一层感知

概念

  • RAII是一种利用对象生命周期来控制程序资源的技术,在对象构造时获取资源 ,最后在对象析构时释放资源。于是我们不用显式释放资源,保证对象析构时候释放资源
  • 这是智能指针的核心原理

智能指针

auto_ptr
  • 管理权转移,拷贝时,会把被拷贝对象的资源管理权转移给拷贝对象
  • 导致被拷贝对象悬空,再次访问该对象时报错
  • 如果不把sp1置空,由于浅拷贝,sp2析构一个后sp1再析构就成了析构空指针
unique_ptr
  • 于auto_ptr的区别在于不能拷贝不能赋值重载
shared_ptr
  • 通过引用计数实现多个shared_ptr对象之间的共享资源
  • 当一个shared_ptr对象销毁时,引用计数--
  • 当引用计数减到0时,才释放资源
  • 支持拷贝构造

注意:引用计数不能使用静态变量 的方式,静态成员变量属于类本身而不是某个具体的对象,所有的类共享这一个静态变量 。当有不同类型的shared_ptr时,一个类型的引用计数--,会影响到另一个不相干的类型引用计数--。所以应该类内定义指针计数,当拷贝构造时将该指针传给this对象,再进行操作。


概念图:

shared_ptr的实现
cpp 复制代码
namespace Mshared_ptr
{
	template<class T>
	class Mshared_ptr
	{
	public:
		Mshared_ptr(T* ptr = nullptr) :_ptr(ptr), _pcount(new int(1)) {}
		
		Mshared_ptr<T>& operator=(Mshared_ptr<T>& ap)
		{
			if (_ptr == ap._ptr)
			{
				return this;
			}
			if (--(*_pcount) == 0)
			{
				delete _ptr; 
				delete _pcount;
			}
			_ptr = ap._ptr;
			_pcount = ap._pcount;
			_pcount++;
			return *this;
		}
		Mshared_ptr(const Mshared_ptr<T>& up):_ptr(up._ptr), _pcount(up._pcount)
		{
			*(_pcount)++;
		}

		T& operator*() { return *_ptr; }
		T* operator->() { return _ptr; }
		T* getPtr() const
		{
			return _ptr;
		}

		int Rcount() const
		{
			return *_pcount;
		}


		~Mshared_ptr() { 
			if (--(*_pcount) == 0)
			{
				cout << "delete ->" << _ptr << endl; 
				delete _ptr;
				delete _pcount;
			}
		}
	private:
		T* _ptr;
		int* _pcount;
	};
};
情景1:
相关推荐
樱木Plus18 小时前
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
c++
blasit3 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_4 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星4 天前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛6 天前
delete又未完全delete
c++
端平入洛7 天前
auto有时不auto
c++
郑州光合科技余经理7 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1237 天前
matlab画图工具
开发语言·matlab
dustcell.7 天前
haproxy七层代理
java·开发语言·前端
norlan_jame7 天前
C-PHY与D-PHY差异
c语言·开发语言