交换和移动无限递归

swap and move infinite recursion

我有一个非常简单的示例 class,使用 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 是否更改为成员交换或类似的东西?

您从未调用过operator=;您所有的代码都使用 initialization (which invokes constructors), specifically copy initialization,而不是赋值(调用 operator=)。

将代码更改为:

name n1{"mr", "john", "smith"};
name n2, n3;

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

你会看到你的 operator= 被使用(并且可能会爆炸)。

  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=() 永远不会被调用,初始化将仅使用您的 class 构造函数完成。