shared_ptr使用的时候需要注意防止裸指针重复赋值给不同的shared_ptr,会造成对象的重复析构,如下程序会发生崩溃
shard_test *pc = new shard_test();
{
std::shared_ptr<shard_test> p1(pc);
ncount = p1.use_count();
std::shared_ptr<shard_test> p2(pc);
ncount = p1.use_count();
}
为了解决该问题,可以将p1赋值给p2,但是很多情况下,我们不太方便拿到p1,c++提供了类本身就获取一个shared_ptr,即shared_from_this()
想使用shared_from_this,在定义类的时候需要继承std::enable_shared_from_this<T>,如下所示:
class shard_test : public std::enable_shared_from_this<shard_test> {
public:
shard_test() {
std::cout << "construct" << std::endl;
}
~shard_test() {
std::cout << "desstruct" << std::endl;
}
};
int main()
{
int ncount = 0;
shard_test *pc = new shard_test();
{
std::shared_ptr<shard_test> p1(pc);
ncount = p1.use_count();
std::shared_ptr<shard_test> p2(pc->shared_from_this());
ncount = p1.use_count();
}
pc = nullptr;
}
上述写法只是为了验证裸指针和shared_from_this(),当我们使用智能指针的时候,最好就不用再使用裸指针,否则很容易因为遗忘造成野指针,上述优化为:
class shard_test : public std::enable_shared_from_this<shard_test> {
public:
shard_test() {
std::cout << "construct" << std::endl;
}
~shard_test() {
std::cout << "desstruct" << std::endl;
}
};
int main()
{
{
std::shared_ptr<shard_test> p1(make_shared<shard_test>());
std::cout << p1.use_count() << std::endl;
std::shared_ptr<shard_test> p2(p1->shared_from_this());
std::cout << p1.use_count() << std::endl;
}
return 0;
}
construct
1
2
desstruct
在一些处理异步流程的时候,使用shared_ptr,也是会存在还没处理完,但是对象已经销毁的情况,此时可以给异步传递一个shared_ptr指针,确保对象的生命周期要长于异步操作,以下是asio里面的用法,可以参考下:
auto self(shared_from_this());
asio::async_read(socket_,
asio::buffer(read_msg_.body(), read_msg_.body_length()),
[this, self](std::error_code ec, std::size_t /*length*/) {
if (!ec) {
room_.deliver(read_msg_);
do_read_header();
}
else {
room_.leave(shared_from_this());
}
});