title: Repeated std::move on an boost::asio socket object in C++11
body: <p>I am exploring using boost::asio along with C++11 features. In particular, I am focusing on an example called "async_tcp_echo_server.cpp", located here (code is also shown at the end of my question):</p>
  
  <p><a href="http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp" rel="noreferrer">http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp</a></p>
  
  <p>My question involves the <code>tcp::socket</code> member <code>socket_</code> of the <code>server</code> class. In the <code>do_accept()</code> method of the <code>server</code> class, <code>socket_</code> is passed to <code>async_accept()</code>. (According to the asio documentation, <code>async_accept()</code> requires, as its first parameter, the <code>socket</code> to accept the connection into.) So far, so good.</p>
  
  <p>The next parameter, the callback for the asynchronous accept operation, is a lambda function. The body of the lambda constructs a new <code>session</code> object, whose constructor also needs the same <code>socket</code>. Interestingly, <code>socket</code> objects cannot be copied; so in the example, the <code>socket_</code> object, which is a member of the <code>server</code> object, is passed using <code>std::move()</code>.</p>
  
  <p>I understand that the "one and only" <code>socket_</code> object (which is a "permanent" member of the <code>server</code> object) is "moved" into the <code>session</code> object. Fine -- <code>socket</code> object is not copied, but moved -- everybody's happy.</p>
  
  <p>But what happens on the next call to <code>async_accept()</code>? Is the same <code>socket_</code> (member of <code>server</code>), that was previously moved, passed in again? When we "move" a member, what is left behind? Is there a magical fountain of unlimited <code>socket</code> objects?</p>
  
  <p>Or is something really less-than-obvious happening here? When the <code>socket</code> is moved into the <code>session</code>, is the contents of the "left behind/moved from" object (<code>socket_</code> member of <code>server</code>) <em>swapped</em> with the contents of the "new" <code>session</code> object's own "not-yet-constructed" <code>socket_</code> member? Am I even making sense?</p>
  
  <h1>Summary</h1>
  
  <p>Code is below. Program flow is fairly simple. <code>main()</code> constructs a single <code>server</code> object. The <code>server</code> makes repeated calls to <code>async_accept()</code>. Each <code>async_accept()</code> callback creates a new <code>session</code> object, each constructed with a (fresh?) <code>socket</code>. Where do all the "fresh" <code>socket</code> objects come from, if they are simply (repeatedly) "moved" from the same <code>socket_</code> member in the (single) <code>server</code>?</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  #include &lt;memory&gt;
  #include &lt;utility&gt;
  #include &lt;boost/asio.hpp&gt;
  
  using boost::asio::ip::tcp;
  
  class session
  : public std::enable_shared_from_this&lt;session&gt;
  {
  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&amp; 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&lt;session&gt;( std::move( socket_ ) )-&gt;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 &lt;&lt; "Usage: async_tcp_echo_server &lt;port&gt;\n";
              return 1;
          }
  
          boost::asio::io_service io_service;
  
          server s( io_service, std::atoi( argv[1] ) );
  
          io_service.run();
  
      } catch( std::exception&amp; e ) {
          std::cerr &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; "\n";
      }
  
      return 0;
  } 
  </code></pre>