поменять местами и переместить бесконечную рекурсию - PullRequest
1 голос
/ 26 апреля 2019

У меня есть очень простой пример класса, скомпилированный с 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 заменен на членский обмен или что-то в этом роде?

Ответы [ 2 ]

5 голосов
/ 26 апреля 2019

Вы никогда не вызывали operator=; весь ваш код использует инициализация (которая вызывает конструкторы), в частности копирование инициализации , а не присваивание (которое вызывает operator=).

Измените код на:

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

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

и вы увидите, что ваш operator= используется (и предположительно взорвется).

2 голосов
/ 26 апреля 2019
  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=() никогда не вызывается, инициализация будет выполняться только с использованием ваших конструкторов классов.

...