首页 > 解决方案 > 用户定义交换方法的可行性

问题描述

考虑到这个话题,我有一个想法(鉴于我正在谈论),应该只为不提供 的类型提供C++11用户定义,更准确地说是运算符(因为我认为更常见的是虽然缺少操作员);or the and/or operator 有一些不希望发生的副作用。swapmove semanticmove assignmentmove ctrmove assignmentmove ctormove assignment

让我们看看示例:[与链接主题中的相同]

class remote_connection
{
public:
  int socket_fd;

  friend void swap( remote_connection& lhs, remote_connection& rhs ) = delete;
}

由于我们没有提供用户定义swap的代码,试图交换一个remote_connection类型的对象调用一个swap实例化的代码,std::swap从而导致一个移动构造和两个移动分配发生(如@1201ProgramAlarm所示)。

因此,要交换对象,编译器会发出以下问题:一个对 a 的函数调用std::swap,一个对 a 的调用move ctr和两个对move assign运算符的调用。这导致 3 个int副本进行实际交换。

结果:4 个函数调用和3 个副本。

让我们实现一个swap方法:

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这会导致发生 3 个副本int(从 rhs 创建一个 tmp,将一个 lhs 复制到 rhs,将 tmp 复制到 lhs )。

因此,要交换对象,编译器会发出问题:一个对 a 的函数调用swap(由 ADL 发现),一个对 a 的调用std::swap(int&, int&)。这也导致 3 个int副本进行实际交换。

结果:2 个函数调用和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 );  
  } 
}

这里我们有:8个函数调用和6 个副本。但如果我们不提供 user-defined swap,我们将有:4 个函数调用和6 个副本。

因此,似乎无论我们拥有什么类(派生自具有大量成员的类,由大量内置和用户定义类型的子对象组成),恕我直言,不提供用户定义的swap. 不仅如此,而且这样的swap很难支持(如果我们在课堂上更改了某些内容而忘记反映这些更改,swap我们会感到惊讶。)

move ctr所以问题是:“如果我们在/中没有副作用move assign operator并同时提供它们,我们是否必须实现 user-defined swap,或者在这种情况下依赖stl提供的一个是一种好习惯?”

抱歉这么多,我不是母语人士:)

PS我忘了补充一点,恕我直言,swap如果我们要实现一个copy-and-swap成语并且我们已经实现了一个move assignment运算符,那么我们需要一个用户定义的。

标签: c++c++11swap

解决方案


推荐阅读