考虑this topic我有一个想法(考虑到我正在谈论C++11
),用户定义的swap
应该仅针对哪些类型提供; t提供move semantic
,更确切地说是move assignment
运算符(因为我认为move ctr
更为常见,而move assignment
缺少move ctor
操作者);或者move assignment
和/或class remote_connection
{
public:
int socket_fd;
friend void swap( remote_connection& lhs, remote_connection& rhs ) = delete;
}
运算符会产生一些不希望发生的副作用。
让我们看看例子:[与链接主题相同]
swap
由于我们没有提供用户定义的remote_connection
,尝试交换swap
类型对象的代码会调用从std::swap
实例化的std::swap
,从而导致移动构造并且两个移动分配发生(如@1201ProgramAlarm所示)。
因此,要交换编译器发出的对象:一个函数调用move ctr
,一个调用move assign
,两个调用int
运算符。这导致3 swap
份副本进行实际交换。
结果: 4 函数调用和 3 副本。
让我们实现class remote_connection
{
public:
int socket_fd;
friend void swap( remote_connection& lhs, remote_connection& rhs )
{
using std::swap;
swap( lhs.socket_fd, rhs.socket_fd );
}
}
方法:
swap
由于我们提供了一个用户定义的remote_connection
,尝试交换swap
类型对象的代码会调用此用户定义的int
,这会导致swap
的3个副本发生(从rhs创建一个tmp,将lhs复制到rhs,将tmp复制到lhs)。
因此,要交换编译器发出的对象:一个函数调用std::swap(int&, int&)
(由ADL找到),一次调用int
。这也导致3 class remote_connection
{
public:
int socket_fd;
int a, b, c, d, e;
friend void swap( remote_connection& lhs, remote_connection& rhs )
{
using std::swap;
swap( lhs.socket_fd, rhs.socket_fd );
swap( lhs.a, rhs.a );
swap( lhs.b, rhs.b );
swap( lhs.c, rhs.c );
swap( lhs.d, rhs.d );
swap( lhs.e, rhs.e );
}
}
份副本进行实际交换。
因此: 2 函数调用和 3 副本。
用户定义的交换赢了,但如果我们在我们的类中添加一些成员会怎么样:
swap
我们有: 8 函数调用和 6 副本。
但如果我们没有提供用户定义的swap
,我们就会有: 4 函数调用和 6 副本。
所以,似乎无论我们拥有什么类(来自具有大量成员的类,由内置和用户定义类型的大量子对象组成),恕我直言,恕我直言,不提供用户定义的swap
。不仅如此,而且swap
难以支持(如果我们在课堂上改变某些内容而忘记反映move ctr
中的变化,我们会感到意外。)
所以问题是:"如果我们在move assign
operator
/ swap
中没有任何副作用并同时提供它们,我们是否必须实施用户定义的stl
,或者在这种情况下依赖swap
提供的一个是好的做法吗?"
很抱歉如此,我不是母语人士:)
P.S。如果我们要实现copy-and-swap
惯用语并且我们已经实现了move assignment
运算符,我忘了添加我们需要的恕我直言,用户定义{{1}}。