代码之家  ›  专栏  ›  技术社区  ›  meguli

交换和移动无限递归

c++
  •  0
  • meguli  · 技术社区  · 6 年前

    我有一个非常简单的示例类,用C++ 17编译。

    #include <string>
    #include <iostream>
    
    struct name {
        std::string first, middle, last;
        name() = default;
        name(name const&) = default;
        name(name &&) = default;
    
        name& operator=(name o) {
            std::swap(*this, o); // bad!
            return *this;
        }
    };
    int main() {
        name n1{"mr", "john", "smith"};
        name n2 = std::move(n1); 
        name n3 = n2;
    
        std::cout << n3.first << " " << n3.middle << " " << n3.last;
    } 
    

    使用这个值语义,捆绑移动分配和我故意称为限定交换,而不是 using std::swap; swap(*this, o); . 无论如何,我没有提供我的交换。我认为STL将交换作为一个移动构造和一系列移动分配来实现,我认为这个实现将无限地重复,交换调用移动和移动调用交换。是 std::swap 换成会员交换还是类似的?

    0 回复  |  直到 6 年前
        1
  •  5
  •   ShadowRanger    6 年前

    你从来没有打过电话 operator= ;所有代码都在使用 initialization (调用构造函数),具体来说 copy initialization ,而不是分配(调用 操作员= )

    将代码更改为:

    name n1{"mr", "john", "smith"};
    name n2, n3;
    
    n2 = std::move(n1); 
    n3 = n2;
    

    你会看到你的 操作员= 使用(可能爆炸)。

        2
  •  2
  •   Dmitry    6 年前
    1. 因为你还没有定义自己的 swap() ,正在写入 std::swap(*this, o); using std::swap; swap(*this, o); 是相同的事情(在代码示例的框架内),并没有真正强调这种编写的意图:在没有ADL的情况下, std::swap 两种情况下都会使用版本。

    2. 在你的声明中:

      name n2 = std::move(n1); 
      name n3 = n2;
      

    operator=() 从不调用,初始化将只使用类构造函数完成。