【c++】std::bind的使用方法深一层理解

10 篇文章 1 订阅
本文深入探讨了C++中std::bind的使用,特别是析构函数中如何避免对象析构后的安全问题。通过分析muduo库的TcpClient析构函数,展示了如何正确绑定外部对象的成员函数,以确保在对象销毁后,相关操作不会导致非法内存访问。同时,文章指出在使用std::bind时应考虑对象的有效性,并提出了成员函数与非成员函数的绑定差异。
摘要由CSDN通过智能技术生成

之前对std::bind使用时,往往在类CA中std::bind(&CA::func, this),其中的func是类CA的一个成员函数,后面带入的this往往是无脑的写入其中。

muduo中TcpClient析构函数源码如下:
 

TcpClient::~TcpClient()
{
  LOG_INFO << "TcpClient::~TcpClient[" << name_
           << "] - connector " << get_pointer(connector_);
  TcpConnectionPtr conn;
  bool unique = false;
  {
    MutexLockGuard lock(mutex_);
    unique = connection_.unique();
    conn = connection_;
  }
  if (conn)
  {
    assert(loop_ == conn->getLoop());
    // FIXME: not 100% safe, if we are in different thread
    CloseCallback cb = std::bind(&detail::removeConnection, loop_, _1);
    loop_->runInLoop(
        std::bind(&TcpConnection::setCloseCallback, conn, cb));
    if (unique)
    {
      conn->forceClose();
    }
  }
  else
  {
    connector_->stop();
    // FIXME: HACK
    loop_->runAfter(1, std::bind(&detail::removeConnector, connector_));
  }
}

今天在看muduo的TcpClient::~TcpClient类时,发现CloseCallback cb = std::bind(&detail::removeConnection, loop_, _1);并没有将类自身的指针传入std::bind中,而是将外面一个对象(EventLoop类)的函数及指针传入其中。
这样作者就很好的避免了,对象析构之后,外面某个调用还来操作析构对象原来操作的内存,导致因为操作非法内存系统崩溃。

进一步思考:为什么TcpClient的TcpConnection没有作为成员变量,生命周期随着TcpClient的生命周期而生死。其中析构函数的loop_->runInLoop(std::bind(&TcpConnection::setCloseCallback, conn, cb));这一句可以说明问题。TcpClient析构之后,TcpConnection还有后续的处理。

(1)对于类的成员函数来讲,需要采用std::bind(&类名::函数名, 类对象的指针,函数参数列表)的方式指定具体的函数对象;如,上述loop_->runInLoop(std::bind(&TcpConnection::setCloseCallback, conn, cb));
(2)对于非类的成员函数来讲,只需要采用std::bind(&函数名, 函数参数列表)的方式即可;如:上述CloseCallback cb = std::bind(&detail::removeConnection, loop_, _1);。//  此处的detail为namespace

由此想到之前无脑写入this,没有考虑对象析构之后的相关处理。因此在函数对象要考虑一下执行该函数对象时,对象是否还有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值