提升回声服务器示例并在 lambda 中捕获 this 和 shared_from_this()

K. *_*sky 2 c++ lambda boost boost-asio

在 boost async-tcp-echo-server示例中,有一个服务器类可以在新连接上创建会话:

acceptor.async_accept(socket, [this](boost::system::error_code ec) {
    if (!ec)
        std::make_shared<session>(std::move(socket))->start();
    do_accept();
});
Run Code Online (Sandbox Code Playgroud)

session::start() 函数体:

void start() { do_read(); }
Run Code Online (Sandbox Code Playgroud)

session::do_read 方法是一个私有成员函数:

void do_read()
{
    auto self(shared_from_this());
    socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
        [this, self](boost::system::error_code ec, std::size_t length) {
            if (!ec)
                do_write(length);
    });
}
Run Code Online (Sandbox Code Playgroud)

如果我错了,请纠正我。
会话类继承自,std::enable_shared_from_this因此在调用时已经创建了一个控制块,shared_from_this()并且不会发生未定义的行为。在do_read函数中,shared_from_this()函数用于允许do_write()对仍然存在于内存中的对象调用方法。如果shared_from_this()不使用该对象,则可以在到达范围结束时删除该对象。

为什么this在 lambda 表达式中被捕获?方法
do_write()调用this还是self

在 C++14 中,我可以替换:

auto self(shared_from_this());
socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
    [this, self] ...
Run Code Online (Sandbox Code Playgroud)

和:

socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
        [this, shared_from_this()] ...
Run Code Online (Sandbox Code Playgroud)

? 或者即使这样:

socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
    [self = shared_from_this()](boost::system::error_code ec, std::size_t length) {
        if (!ec)
            self->do_write(length);
});  
Run Code Online (Sandbox Code Playgroud)

?

lis*_*rus 5

self对象被捕获到lambda作为一种所有权凭证:只要拉姆达生活,令牌的生活,并且对象不会被破坏。

捕获this在这里是多余的,但没有它就必须写

if (!ec)
    self->do_write(length);
Run Code Online (Sandbox Code Playgroud)

代替

if (!ec)
    do_write(length);
Run Code Online (Sandbox Code Playgroud)

这与

if (!ec)
    this->do_write(length);
Run Code Online (Sandbox Code Playgroud)

因此,this主要是为了可读性而被捕获。