首先,作者根据股票创建了一个基本的股票对象池,如果股票被用到,则共享,如果用不到则析构。
version 1
class StockFactory:boost::noncopyable{
public:
shared_ptr<Stock> get(const string &key);
private:
mutable MutexLock mutex_;
std::map<string ,shared_ptr<Stock>> stocks_;
}
//作者说这里用智能指针有问题,因stocks_中Stock对象的生命周期与StockFactory绑定了,只有StockFactory析构的时候,里面的stocks_才会析构,最终释放里面的智能指针。
所以,作者改成了version2
std::map<string ,weak_ptr<Stock>> stocks_;//这里改成了弱智猪
shared_ptr<Stock> StockFactory::get(const string &key){
shared_ptr<Stock> pStock;
MutexLockGuard lock(mutex);
weak_ptr<Stock>& wkStock=stocks_[key];
pStock=wkStock.lock();
if(!pStock){
pStock.reset(new Stock(key));
wkStock=pStock;
}
return pStock;
}
作者说这里出现了内存泄露,这是因为stocks_里面虽然Stock对象销毁了,但是key还在,所以如果所有对象都不存在的情况下,stocks_里面有以前所有的key,对应null,这是个轻微的内存泄露。
所以有了version3版本
解决办法是:为shared_ptr定制了一个析构功能
class StockFactory:boost ::noncopyable{
//在这里,将get(),pStock.reset(new Stock(key));改为pStock.reset(new Stock(key),
//boost::bind(&StockFactory::deleteStock,this ,_1));
private:
void deleteStock(Stock *stock){
if(stock){
MutexLockGuard lock(mutex_);
stocks_.erase(stock->key());
}
delete stock;
}
}
这里要稍微了解一下boost::bind()函数,
https://blog.csdn.net/yansmile1/article/details/55266059
主要有一句话:
类的成员函数不同于普通的函数,因为成员函数指针不能直接调用operator(),它必须被绑定到一个对象或指针,然后才能得到this指针进而调用成员函数。因此bind需要 “牺牲”一个占位符,要求提供一个类的实例、引用或者指针,通过对象作为第一个参数来调用成员函数,即:
bind(&X::func,x,_1,_2,…)
1 demo a,&ra = a; //类的实例对象和引用
2 demo * p = & a; //指针
3 cout<<bind(&demo::f,a,_1,20)(10)<<endl;
4 cout<<bind(&demo::f,ra,_2,_1)(10,20)<<endl;
5 cout<<bind(&demo::f,p,_1,_2)(10,20)<<endl;
这一块对应源代码里面的
pStock.reset(new Stock(key),boost::bind(&StockFactory::deleteStock,this ,_1));
也即是this必须要传入进来,后的参数是_1,占位符。所以delete stock;是delete 前面new Stock(key)创建的对象。
根据上述所述,因为传入了this,所以这里又要保证this的安全,下面把this也作为智能指针
version 4
class StockFactory:public boost::enable_shared_form——this<StockFactory>,boost::noncopyable{
}
pStock.reset(new Stock(key),boost::bind(&StockFactory::deleteStock,shared_from_this(),_1);
//.....
这样保证调研deleteStock的时候StockFactory还活着。
note:
shared_from_this() 不能在构造函数里面调用,因为在构造StockFactory的时候,它还没有被交给shared_ptr接管。
最后一个问题,就是StockFactory生命周期被延长了,这里this也是可以用弱回调。
version5
class StockFactory:public boost :: enable_shared_from_this<StockFactory>,boost::noncopyable{
public:
shared_ptr<Stock> get(const string &key){
shared_otr<Stock> pStock;
MutexLockGuard lock(mutex_);
weak_Ptr<Stock>& wkStock=stocks_[key];
pStock=wkStock.lock();
if(!pStock){
pStock.reset(new Stock(key),
boost::bind(&StockFactory::weakDeleteCallback,
boost::weak_ptr<StockFactory>(shared_from_this()),
_1));
wiStock=pStock;
}
return pStock;
}
private:
static void weakDeleteCallback(const boost::weak_ptr<StockFactory>& wkFactory,Stock* stock){
shared_ptr<StockFactory> factory(wkFactory.lock());
if(factory){
factory->removeStock(stock);
}
delete stock;
}
}