在C+;中的boost::asio套接字对象上重复std::move+;11

在C+;中的boost::asio套接字对象上重复std::move+;11,boost,c++11,boost-asio,move,move-semantics,Boost,C++11,Boost Asio,Move,Move Semantics,我正在探索使用boost::asio和C++11特性。特别是,我将重点放在一个名为“async_tcp_echo_server.cpp”的示例上,该示例位于此处(问题末尾还显示了代码): 我的问题涉及server类的tcp::socket成员socket。在server类的do\u accept()方法中,socket被传递给async\u accept()。(根据asio文档,async_accept()要求将接受连接的socket作为其第一个参数。)到目前为止,一切正常 下一个参数,异步接

我正在探索使用boost::asio和C++11特性。特别是,我将重点放在一个名为“async_tcp_echo_server.cpp”的示例上,该示例位于此处(问题末尾还显示了代码):

我的问题涉及
server
类的
tcp::socket
成员
socket
。在
server
类的
do\u accept()
方法中,
socket
被传递给
async\u accept()
。(根据asio文档,
async_accept()
要求将接受连接的
socket
作为其第一个参数。)到目前为止,一切正常

下一个参数,异步接受操作的回调,是一个lambda函数。lambda的主体构造了一个新的
会话
对象,其构造函数也需要相同的
套接字
。有趣的是,
socket
对象无法复制;因此,在本例中,使用
std::move()
传递
socket\uuu
对象,该对象是
服务器
对象的成员

我知道“唯一的”
socket\uuu
对象(是
服务器
对象的“永久”成员)已“移动”到
会话
对象中。很好--
socket
对象不是复制的,而是移动的--每个人都很高兴

但是下次调用
async\u accept()
时会发生什么?先前移动的
套接字
(服务器的成员)是否再次传入?当我们“移动”一个成员时,会留下什么?是否有无限的
socket
对象的神奇喷泉

还是这里真的发生了一些不太明显的事情?当
套接字
被移动到
会话
中时,对象(
服务器
套接字
成员)的“遗留/移动”内容是否与“新的”
会话
对象自己的“尚未构建”
套接字
成员的内容交换?我说得通吗

总结 代码如下。程序流程相当简单
main()
构造一个
server
对象。
服务器反复调用
async\u accept()
。每个
async\u accept()
回调都会创建一个新的
会话
对象,每个对象都由一个(新的?
套接字
构造。如果所有的“新的”
socket
对象只是从(单个)
服务器中的同一
socket\uu
成员(重复)“移动”过来,那么它们从哪里来

#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class session
: public std::enable_shared_from_this<session>
{
public:
    session( tcp::socket socket )
    : socket_( std::move( socket ) )
    {}

    void start() {
        do_read();
    }

private:
    void do_read() {
        auto self( shared_from_this() );
        socket_.async_read_some(
            boost::asio::buffer( data_, max_length ),
            [this, self]( boost::system::error_code ec, std::size_t length )
            {
                if( !ec ) {
                    do_write( length );
                }
            }
        );
    }

    void do_write( std::size_t length ) {
        auto self( shared_from_this() );
        boost::asio::async_write(
            socket_,
            boost::asio::buffer( data_, length ),
            [this, self]( boost::system::error_code ec, std::size_t /*length*/ )
            {
                if( !ec ) {
                    do_read();
                }
            }
        );
    }

    tcp::socket socket_;
    enum { max_length = 1024 };
    char data_[max_length];
};


class server {
public:
    server( boost::asio::io_service& io_service, short port )
    : acceptor_( io_service, tcp::endpoint( tcp::v4(), port ) )
    , socket_( io_service )
    {
        do_accept();
    }

private:
    void do_accept() {
        acceptor_.async_accept(
            socket_,
            [this]( boost::system::error_code ec )
            {
               if( !ec ) {
                   std::make_shared<session>( std::move( socket_ ) )->start();  // is this a *swap* of socket_ ???
               }

               do_accept();
            }
        );
    }

    tcp::acceptor acceptor_;
    tcp::socket socket_;
};


int main( int argc, char* argv[] ) {
    try {
        if( argc != 2 ) {
            std::cerr << "Usage: async_tcp_echo_server <port>\n";
            return 1;
        }

        boost::asio::io_service io_service;

        server s( io_service, std::atoi( argv[1] ) );

        io_service.run();

    } catch( std::exception& e ) {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
} 
#包括
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
课堂
:public std::从\u中启用\u共享\u
{
公众:
会话(tcp::套接字)
:插座(标准::移动(插座))
{}
void start(){
你读过吗;
}
私人:
void do_read(){
自动自我(从_this()共享_);
套接字异步读取(
boost::asio::buffer(数据长度,最大长度),
[this,self](boost::system::error\u code ec,std::size\u t length)
{
如果(!ec){
不写(长度);
}
}
);
}
无效写入(标准::大小\u t长度){
自动自我(从_this()共享_);
boost::asio::异步写入(
插座,
boost::asio::buffer(数据,长度),
[this,self](boost::system::error\u code ec,std::size\u t/*length*/)
{
如果(!ec){
你读过吗;
}
}
);
}
tcp::socket-socket;
枚举{max_length=1024};
字符数据[最大长度];
};
类服务器{
公众:
服务器(boost::asio::io_服务和io_服务,短端口)
:接受者(io_服务,tcp::端点(tcp::v4(),端口))
,套接字(io_服务)
{
你接受吗;
}
私人:
无效不接受{
接受方\异步\接受方(
插座,
[this](boost::system::error_code ec)
{
如果(!ec){
std::make_shared(std::move(socket_u))->start();//这是socket_uu的交换吗???
}
你接受吗;
}
);
}
tcp::接受者接受者;
tcp::socket-socket;
};
int main(int argc,char*argv[]){
试一试{
如果(argc!=2){
标准::cerr如以下文件所述:

移动后,从对象移动的对象处于与 使用基本流套接字(io_服务&)构造函数构造


上面的意思是,您可以根据需要将原始的
套接字
对象从
服务器
移动到
会话

移动语义可以被认为是传递资源的所有权。资源获取是实例化(RAII)是在对象构造时分配资源的所有权并在销毁时释放这些资源的概念。移动语义允许在除构造和销毁之外的其他时间转移资源的所有权

在这种情况下,对象(
server::socket
)是从
server::acceptor
转移OS套接字资源所有权的接收者。该转移发生在
async\u accept()之后的某个时间点
在客户端连接时返回。新连接的套接字资源被移动到
socket\u
中,并调用回调lambda函数。在lambda过程中,套接字资源被移动到
会话::socket\u
。服务器::socket\uuu。仅在几分之一微秒的时间内拥有该资源

移动语义允许RAII类在不拥有任何资源的暮色状态下存在。考虑调用release后的
unique\u ptr
(它表示没有内存)。移出后的server::socket仍然有空间容纳资源,但是