智能指针
参见
什么是智能指针?
智能指针是一个句柄
智能指针在离开作用域时自动调用实际指针的析构函数
第一点句柄代表了智能指针本身不会失效,因此没有判空问题
第二点代表了智能指针可以自动管理内存
weak_ptr
weak_ptr 用于关联到一个 shared_ptr 上。而且这个关联不会导致 shared_ptr 中的引用计数增加。主要目的是防止环形引用
weak_ptr 比较重要的一点是用来做资源的 handle,这样就不用担心空指针的问题了,因为 handle 是不会失效的
另外
析构动作在创建时被捕获
这是一个非常有用的特性,这意味着:
虚析构不再是必需的
shared_ptr<void> 可以持有任何对象,而且能安全地释放
shared_ptr 对象可以安全地跨越模块边界,比如从 DLL 里返回,而不会造成从模块 A 分配的内存在模块 B 里被释放这种错误
二进制兼容性,即便 Foo 对象的大小变了,那么旧的客户代码仍然可以使用新的动态库,而无须重新编译。前提是 Foo 的头文件中不出现访问对象的成员的 inline 函数,并且 Foo 对象的由动态库中的 Factory 构造,返回其 shared_ptr
析构动作可以定制
析构所在的线程
对象的析构是同步的,当最后一个指向 x 的 shared_ptr 离开其作用域的时候,x 会同时在同一个线程析构。这个线程不一定是对象诞生的线程。
这个特性是把双刃剑:如果对象的析构比较耗时,那么可能会拖慢关键线程的速度(如果最后一个 shared_ptr 引发的析构发生在关键线程);同时,我们可以用一个单独的线程来专门做析构,通过一个 BlockingQueue<shared_ptr<void> > 把对象的析构都转移到那个专用线程,从而解放关键线程。
std::shared_ptr<Node> getptr() {
return shared_ptr<Node>(this);
}
没问题,但是
this->shared_from_this()
会出现问题
对象池
对象池算是对智能指针指针的一次综合运用
class Stock {
string key_;
public:
Stock(string key) : key_(key) { }
const string& key() {
return key_;
}
};
class StockFactory : enable_shared_from_this<StockFactory> {
mutable mutex mutex_;
map<string, weak_ptr<Stock>> stocks_;
public:
shared_ptr<Stock> get(const string& key) {
std::lock_guard<mutex> lock(mutex_);
auto& wkStock = stocks_[key];
auto pStock = wkStock.lock();
if(!pStock) {
pStock.reset(new Stock(key), bind(&StockFactory::weakDeleteCallBack,
weak_ptr<StockFactory>(this->shared_from_this()), std::placeholders::_1));
}
return pStock;
}
static void weakDeleteCallBack(const weak_ptr<StockFactory>& wkFactory, Stock* stock) {
auto factory = wkFactory.lock();
if(factory) factory->removeStock(stock);
delete stock;
}
void removeStock(Stock* stock) {
if(stock) {
lock_guard<mutex> lock(mutex_);
stocks_.erase(stock->key());
}
}
};