为用户定义的类型提供 swap() 的原因是什么?
What's a reason to provide a swap() for the user defined type?
例如,我有一个 class 管理着一个 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<T>()
模板函数的 std::swap<remote_connection>()
函数。该函数实现调用移动构造函数和移动赋值运算符,这会导致对象交换它们的内容。
我可以为 remote_connection
实现一个 swap()
,这会产生相同的结果。
所以问题是我可以在 swap
中为 class 做什么 template std::swap<T>()
做不到的事情?或者为什么我们应该为一个类型提供一个实现,如果它可以被编译器实例化,即使对于管理不平凡的子对象(POSIX fd,指针,...)的类型也是如此?
全局 std::swap
需要创建一个临时文件。基于自定义 class 的交换将了解 class 的内部结构,并且可以更有效地进行交换,而无需创建另一个 class 类型的变量。
在你的情况下,内部交换可以只交换内部 socket_id
值,而不必在移动构造函数和移动赋值运算符(将被调用两次)中做所有额外的事情。
例如,我有一个 class 管理着一个 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<T>()
模板函数的 std::swap<remote_connection>()
函数。该函数实现调用移动构造函数和移动赋值运算符,这会导致对象交换它们的内容。
我可以为 remote_connection
实现一个 swap()
,这会产生相同的结果。
所以问题是我可以在 swap
中为 class 做什么 template std::swap<T>()
做不到的事情?或者为什么我们应该为一个类型提供一个实现,如果它可以被编译器实例化,即使对于管理不平凡的子对象(POSIX fd,指针,...)的类型也是如此?
全局 std::swap
需要创建一个临时文件。基于自定义 class 的交换将了解 class 的内部结构,并且可以更有效地进行交换,而无需创建另一个 class 类型的变量。
在你的情况下,内部交换可以只交换内部 socket_id
值,而不必在移动构造函数和移动赋值运算符(将被调用两次)中做所有额外的事情。