Причина: локальная переменная «производная» будет скопирована, несмотря на то, что она была возвращена по имени - PullRequest
1 голос
/ 18 апреля 2020

Это продолжение до Является ли предупреждение -Wreturn-std-move clang корректным в случае объектов в той же иерархии? , потому что я не понимаю рассуждения в определенных конкретных c случаях.

struct Field {
  Field();
//  Field(const Field&); // (a)
  int a[1000000];
};

struct Base
{
  Base();
//  Base(const Base&); // (b)
//  Base(Base&&); // (c)
  Field f;
};

struct Derived : Base { };

Base foo()
{
  Derived derived;
  return derived;
}
  1. Приведенный выше код компилируется просто отлично. Я понимаю, что std :: move не сделает ничего другого.
  2. Раскомментируйте (a), вы получите предупреждение. Почему? Я верю, что std :: move все равно не сделает ничего другого.
  3. Раскомментируйте (b) (оставьте (a) без комментариев), снова работает нормально. Чем он отличается от # 2?
  4. Uncomment (c) (оставляйте (a) и (b) без комментариев), снова показывает предупреждение. Это имеет смысл, std :: move может сохранить нам копию.
  5. Пусть foo возвращает Derived, снова работает нормально. Чем он отличается от # 4?

1 Ответ

0 голосов
/ 18 апреля 2020

Как состояние в ответе по ссылке и в cppreference

Сначала мы рассматриваем производное как значение, а если оно не выбирает XXX(/*const*/Derived&&) (до C ++ 20), то мы Пересмотрите его как lvalue.

Так что, пока нет Base(Derived&&), копия сделана.

Хотя я не нашел всего логика c предупреждения., 1. 2. 3. должен обрабатываться в том же IMO (либо нет предупреждений, которые в настоящее время эквивалентны, либо предупреждений для будущего подтверждения).

Для 1.

конструктор копирования и перемещения генерируется компилятором .
копирование или перемещение дают тот же результат в конце.

Для 2.

Field конструктор перемещения больше не генерируется, поэтому вместо перемещения создается полная цепная копия.
Копирование или перемещение дают тот же результат в конце.

Для 3.

Base Конструктор перемещения больше не генерируется, поэтому копирование с начала.
Копирование или перемещение дают то же самое результат в конце.

Для 4.

База имеет конструктор копирования и перемещения.
Копирование или перемещение дают диф первый результат.

Для 5.

Теперь у нас есть совпадение XXX(Derived&&) (XXX = Derieved), поэтому копирование не производится.

...