交换并移动无限递归

时间:2019-04-26 00:25:46

标签: c++ c++17 swap move-semantics

我有一个非常简单的示例类,是用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将交换作为移动构造和一系列移动分配实现,我认为此实现将无限递归,交换调用move和移动调用swap。 std::swap变成了成员交换还是类似的东西?

2 个答案:

答案 0 :(得分:5)

您从未调用过operator=;您所有的代码都使用initialization(调用构造函数),特别是copy initialization,而不是赋值(调用operator=)。

将代码更改为:

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

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

,您会看到operator=被用了(大概爆炸了)。

答案 1 :(得分:2)

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