Будет ли это делать операцию перемещения по умолчанию - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть функция foo:

std::vector<T> foo() {
  std::vector<T> result;
  // populate result
  {
    /*
       for loop with result.push_back().
       ignore real code.
    */
  }
  //
  return result;    <-- note there without std::move
}

Будет ли выполнено дополнительное копирование, если я назначу следующим образом?

const auto v = foo();   <-- will it move the vector by default?
const auto &v = foo();  <-- same question as above, assuming T is movable

Меня особенно интересует второй случай, так как для первого случая это очень вероятно, что компилятор знает, переместить результат из foo () в v.

const auto &v = foo();

Для этого случая функция foo () создает временную переменную result . Теперь, поскольку v является ссылкой, он не может переместить result в v. Таким образом, ему необходимо создать новую копию. Правильно ли мое понимание?

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Компиляторам разрешено любое и все преобразования кода, которые не изменяют наблюдаемое поведение программы , путем применения как-будто правила .

Однако copy_elision является исключением из как-бы правила : компилятор может удалять вызовы конструкторов перемещения и копирования и совпадающие вызовы деструкторов временных объектов , даже если эти вызовы имеют наблюдаемые побочные эффекты . Чтобы увидеть эти побочные эффекты, вы должны использовать опцию -fno-elide-constructors при компиляции.

На странице copy_elision мы должны взглянуть на предложение:

В операторе возврата, когда операндом является имя энергонезависимого объект с автоматическим сроком хранения, который не является функцией параметр или параметр предложения catch, который принадлежит к тому же классу type (игнорируя cv-qualification) в качестве типа возврата функции. это вариант исключения копии известен как NRVO, "названное возвращаемое значение оптимизация».

Короче говоря, когда компилятор видит следующую структуру, он знает, что он является кандидатом на NRVO.

T FunctionName ( ... )
{
    T a;
    ...
    return a;
}

Что соответствует структуре кода вашей проблемы.

std::vector<T> foo() {
  std::vector<T> result;
  // populate result
  {
    /*
       for loop with result.push_back().
       ignore real code.
    */
  }
  return result;
}

То, что вы видите, не семантика движения, это просто NRVO.
Так что вопросы здесь не имеют никакого отношения.

const auto v = foo();   <-- will it move the vector by default?
const auto &v = foo();  <-- same question as above, assuming T is movable

Не имеет значения, является ли T подвижным. Здесь не происходит move.

Мы бы достигли того же результата и в компиляторе до C ++ 11 => http://coliru.stacked -crooked.com / a / 85c097f167b98b99

Для лучшего понимания посмотрите код - http://coliru.stacked -crooked.com / a / 4b9a7e9504ab7aa8 или cat /Archive2/4b/9a7e9504ab7aa8/main.cpp на Coliru.
Затем добавьте -fno-elide-constructors и посмотрите подробный анализ. Там вы можете найти, когда вызывается конструктор перемещения.

0 голосов
/ 03 сентября 2018

В обоих случаях, кажется, нет никакой дополнительной копии, видимой из этой ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...