为用户定义的类型提供swap()的原因是什么?

时间:2018-04-21 19:58:15

标签: c++ c++11 swap

例如,我有一个管理POSIX fd的类:

class remote_connection:
{
public:
  explicit remote_connection( int socket_fd ) : socket_fd(socket_fd) {}
  ~remote_connection() { close( socket_fd); }

  /* no copy semantic */
  remote_connection( const remote_connection& other ) = delete;
  remote_connection& operator=( const remote_connection& rhs ) = delete;

  remote_connection( remote_connection&& other )
  {
    socket_fd = other.socket_fd;
    other.socket_fd = -1;
  }

  remote_connection& operator=( remote_connection&& rhs )
  {
    close( socket_fd );
    socket_fd = rhs.socket_fd;

    rhs.socket_fd = -1;

    return *this;
  } 

private:
  int socket_fd;
};

代码中的某处:

/* let '42' and '24' be a valid fds */
remote_connection cl_1( 42 ), cl_2( 24 );

...

using std::swap;

swap( cl_1, cl_2 );

对于remote_connection ADL的这种实现,我发现没有用户定义swap并且退回到std命名空间,而remote_connection没有专门化,所以编译器从std::swap<remote_connection>()模板函数实例化std::swap<T>()函数。该函数实现调用move ctor并移动赋值运算符,使对象交换其内容。

我可以为导致相同结果的swap()实施remote_connection

所以问题是我可以在swap内针对template std::swap<T>()无法解决的问题具体说明哪些内容?或者为什么我们应该提供一个类型的实现,如果它可以由编译器实例化,即使对于管理不普通的子对象的类型(POSIX fd,pointers,...)?

1 个答案:

答案 0 :(得分:4)

全局std::swap需要创建临时的。基于自定义类的交换将了解类的内部,并且可以更有效地进行交换,而无需创建类类型的另一个变量。

在你的情况下,内部交换只能交换内部socket_id值,而不必在移动构造函数中移动赋值运算符(将被调用两次)。