C++ - NRVO и переезд

Я прочитал несколько постов о функциях перемещения (например, http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html) и хотел наблюдать за ходом операторов в действии. Поэтому я попробовал следующий код:

#include <vector>
#include <cassert>
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;

vector<double> operator+(const vector<double>& a, const vector<double>& b){
  assert(a.size()==b.size());
  vector<double> result(a.size(),0);
    transform (a.begin(), a.end(), b.begin(), result.begin(), std::plus<double>());
  cout<<&result<<endl;
  return result;
}

int main(int argc, char const *argv[]) {
  vector<double> a,b;
  for (int i=0;i<10;i++){
    a.push_back(i);
    b.push_back(1);
  }
  std::vector<double> c=a+b;
  cout<<&c<<endl;
  return 0;
}

Я ожидал получить тот же адрес для локальной переменной result а также c так как операторы перемещения реализованы для vector, И я получил именно это, но с и без флага -std=c++11, Именно тогда я узнал о NRVO ( оптимизация возвращаемого значения C++11 или перемещение?), Поэтому я отключил его с флагом -fno-elide-constructors и теперь адрес другой, даже с флагом -std=c++11, Есть ли проблема с моим кодом или я что-то не так понял в операторах перемещения?

Из того, что я понял, возврата по значению должно быть достаточно для включения оператора перемещения (значения C++11 и путаница в семантике перемещения (оператор return)).

PS: я пробовал с GCC 6.3.0_1 и Apple LLVM версии 8.1.0 .

РЕДАКТИРОВАТЬ

Как указано, я должен был проверить result.data() вместо &result (увидеть ниже). Но в этом случае я всегда находил один и тот же адрес, даже без std=c++11 и с -fno-elide-constructors, Смотрите принятый ответ и его раздел комментариев.

2 ответа

Решение

Думайте о движении как о оптимизированной копии. Это все еще копия, поэтому это все еще другой вектор, но он "переместил" лежащие в основе данные из одного вектора в другой. Вы можете увидеть это, сравнив адрес данных:

cout<<result.data()<<endl;

а также

cout<<c.data()<<endl;

Копия elision, с другой стороны, полностью исключает копию.

Конструктор перемещения создает новый объект путем кражи ресурсов старого. Он вообще не объединяет временные блоки: если конструкция не исключена, у вас все еще есть два объекта.

Другие вопросы по тегам