我是靠谱客的博主 跳跃裙子,最近开发中收集的这篇文章主要介绍【c++】std::bind的使用方法深一层理解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

之前对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,没有考虑对象析构之后的相关处理。因此在函数对象要考虑一下执行该函数对象时,对象是否还有效。

最后

以上就是跳跃裙子为你收集整理的【c++】std::bind的使用方法深一层理解的全部内容,希望文章能够帮你解决【c++】std::bind的使用方法深一层理解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部