当面对下面场景时,发现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:






