Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 从\u启用\u共享\u这对共享\u ptr的使用寿命有何影响?_C++11_Shared Ptr - Fatal编程技术网

C++11 从\u启用\u共享\u这对共享\u ptr的使用寿命有何影响?

C++11 从\u启用\u共享\u这对共享\u ptr的使用寿命有何影响?,c++11,shared-ptr,C++11,Shared Ptr,我正在看boost::asio的一个教程 class tcp_server { public: tcp_server(boost::asio::io_service& io_service) : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13)) { start_accept(); } private: void start_accept() { tcp_connection::poin

我正在看boost::asio的一个教程

class tcp_server
{
public:

  tcp_server(boost::asio::io_service& io_service)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
  {
    start_accept();
  }

private:

  void start_accept()
  {
    tcp_connection::pointer new_connection =
      tcp_connection::create(acceptor_.get_io_service()); // shared_ptr got created.
    acceptor_.async_accept(new_connection->socket(),
      boost::bind(&tcp_server::handle_accept, this, new_connection,
      boost::asio::placeholders::error)); // instance added to io_service task list, but bind does not use shared_ptr internally I believe.
  } // shared_ptr of tcp_connection goes out of scope.

  void handle_accept(tcp_connection::pointer new_connection,
  const boost::system::error_code& error)
  {
    if (!error)
    {
      new_connection->start();
    }
    start_accept();
  }

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:
  typedef boost::shared_ptr<tcp_connection> pointer;

  static pointer create(boost::asio::io_service& io_service)
  {
    return pointer(new tcp_connection(io_service));
  }

  tcp::socket& socket()
  {
    return socket_;
  }

  void start()
  {
    message_ = make_daytime_string();
    boost::asio::async_write(socket_, boost::asio::buffer(message_),
      boost::bind(&tcp_connection::handle_write, shared_from_this(),
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));
  }

private:
  tcp_connection(boost::asio::io_service& io_service)
    : socket_(io_service)
  {
  }

  void handle_write(const boost::system::error_code& /*error*/,
      size_t /*bytes_transferred*/)
  {
  }

  tcp::socket socket_;
  std::string message_;
};
class-tcp\u服务器
{
公众:
tcp_服务器(boost::asio::io_服务和io_服务)
:acceptor_(io_服务,tcp::endpoint(tcp::v4(),13))
{
开始接受();
}
私人:
void start_accept()
{
tcp_连接::指针新建_连接=
tcp_connection::create(acceptor_u.get_io_service());//已创建共享的ptr。
acceptor\异步\u accept(新建\u连接->套接字(),
boost::bind(&tcp\u server::handle\u accept,这个,新的\u连接,
boost::asio::placeholders::error));//实例已添加到io_服务任务列表中,但我相信bind在内部不使用共享_ptr。
}//tcp_连接的共享_ptr超出范围。
无效句柄\u接受(tcp\u连接::指针新\u连接,
常量boost::系统::错误(代码和错误)
{
如果(!错误)
{
新建连接->开始();
}
开始接受();
}
类tcp\u连接
:public boost::从\u启用\u共享\u
{
公众:
typedef boost::共享_ptr指针;
静态指针创建(boost::asio::io_服务和io_服务)
{
返回指针(新的tcp_连接(io_服务));
}
tcp::套接字和套接字()
{
返回插座;
}
void start()
{
message_uu=make_daily_string();
boost::asio::异步写入(套接字),boost::asio::缓冲区(消息),
boost::bind(&tcp_connection::handle_write,shared_from_this(),
boost::asio::占位符::错误,
boost::asio::占位符::字节(已传输);
}
私人:
tcp_连接(boost::asio::io_服务和io_服务)
:socket_(io_服务)
{
}
无效句柄写入(常量boost::system::error\u代码&/*error*/,,
大小\u t/*字节\u传输*/)
{
}
tcp::socket-socket;
std::字符串消息;
};
我发现有一部分运行时,
tcp\u connection
对象的
shared\u ptr
对象没有活动。这似乎意味着
tcp\u connection
对象将在该部分开始时被破坏,因为它的
shared\u ptr
中的计数降为零,这显然不是什么我们想要

但是后来我在类
tcp\u连接中看到了注释

我们将使用shared_ptr并从_启用_shared_,因为我们希望保持tcp_连接对象的活动状态,只要存在引用它的操作


我也搜索了这个问题,并在SO中得到了一个Q&a。但我仍然对标题问题感到困惑。具体地说,
有一个操作引用它是什么意思?
tcp\u server::start\u accept()时
返回,
tcp\u连接
的所有
shared\u ptr
实例应超出范围,并且可能只有一些原始指针引用添加到
io\u服务
任务列表中。如果没有实例,
如何从该
启用\u shared\u防止
tcp\u连接
的堆实例被破坏这个
tcp\u连接
对象的
shared\u ptr
?或者它与从这个对象启用的\u shared\u无关,但是
boost::asio::io\u服务
在内部保持有界异步\u处理程序的
shared\u ptr

这个问题可以通过描述shared\u ptr的非侵入性设计来回答,它可以让我ans不接触其指向对象的“任何”代码

我们可以从它的非侵入式设计中得到很多好处。但另一方面,它不可避免地导致了这样的情况:一旦共享了\u ptr,就到处共享了\u ptr,而没有原始指针。

让我们看看这个片段:

{
    shared_ptr<int> orig_sp{new int};
    shared_ptr<int> good_sp{orig_sp};       // it's ok
    shared_ptr<int> bad_sp{orig_sp.get()};  // leads crashing
}
但问题是
共享\u ptr
ed对象的成员函数想要延长其自身的生命周期

class tcp_connection {
    void start()
    {
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
          boost::bind(&tcp_connection::handle_write, (/* how to fill this field? */),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }
};
  • 在该字段中填写
    是不可接受的,因为它不会延长tcp\U连接的生命周期
  • 填充
    boost::shared_ptr(此)
    也是不可接受的。根据我们的第一个代码片段,它将导致崩溃
  • 也许
    boost::shared\u ptr(tcp\u connection::create(acceptor.get\u io\u service())
    看起来不错,但它试图在其成员中创建对象本身
现在很清楚了。
tcp\u connection::start()
想知道哪个共享ptr被管理,但根据共享ptr的非侵入性设计,
tcp\u connection
不应该包含共享ptr的任何信息。这是不可能的任务

最后,我们必须妥协,并请求
enable\u shared\u from\u this
寻求帮助。
enable\u shared\u from\u this
要求必须使用从中派生类。这就是
tcp\u连接
看起来非常棘手的原因

class tcp_connection : boost::enable_shared_from_this<tcp_connection> {
    void start()
    {
        // ...
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
          boost::bind(&tcp_connection::handle_write, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }
};
class-tcp\u连接:boost::从\u启用\u共享\u{
void start()
{
// ...
boost::asio::异步写入(套接字),boost::asio::缓冲区(消息),
boost::bind(&tcp_connection::handle_write,shared_from_this(),
boost::asio::占位符::错误,
boost::asio::占位符::字节(已传输);
}
};

enable_shared_from_this
模板为共享_ptr保留了一些字段,如引用计数,并为那些成员函数希望使用共享_ptr而不是
this
的函数提供了
shared_from_this
对象由functor保持活动状态

请注意,
handle\u accept
回调函数如何将
shared\u ptr
tcp\u连接
作为参数。魔法现在发生在
boost::bind
调用中,该调用用于指定对
async\u accept
的回调

该bind调用返回一个functor对象,该对象按值存储调用
handle\u accept
所需的所有参数。因此,bind返回的functor包含
shared\u ptr
tcp\u连接的副本,从而使其保持活动状态。functor(将其视为
boost::function
)现在依次由t复制
class tcp_connection : boost::enable_shared_from_this<tcp_connection> {
    void start()
    {
        // ...
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
          boost::bind(&tcp_connection::handle_write, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }
};