Переместить семантику на отдельные элементы вектора - PullRequest
0 голосов
/ 30 марта 2019

Каково поведение std::move на отдельном элементе вектора? например (следует чрезвычайно упрощенный код)

Будет ли это делать правильный ход, и мне нужно erase() перемещенный элемент?

Обычно я использую конструктор копирования и удаление, оптимизирует ли компилятор движение (синтезированное) вместо использования конструктора копирования в некоторых случаях?

Я попытался использовать обертки со смарт-указателями и не увидел значительного ускорения. Семантика перемещения выглядит как то, что я хочу использовать.

template< class T >
class Foo
{
};

vector< Foo< T > > v1, v2;

v2.emplace_back( std::move( v1[ 2 ] );

Я не вижу значительного ускорения при использовании операций перемещения, и мне кажется, что я правильно реализовал конструктор перемещения и оператор присваивания перемещения.

Пожалуйста, пролите свет на эту проблему.

1 Ответ

0 голосов
/ 31 марта 2019

Семантика перемещения имеет два задания:

  • Указывает, что владение ресурсом (например, выделенной памятью, указателем FILE * или потоком) перешло в другие руки
  • Избегайте ненужных копий в вышеуказанных случаях.

Например, допустим, у нас есть вектор:

vector<int> a; 
for(int i = 0; i < 10000; i++) { 
    a.push_back(i); 
}

Если я напишу:

vector<int> b = a;

Это делает копию каждого отдельного элемента в a, поэтому это медленная операция. Однако, если я напишу

vector<int> b = std::move(a); 

Ни один из элементов в a не копируется, и в итоге получается намного быстрее. Однако a больше не владеет этими элементами. Мы можем продемонстрировать это, используя следующий код:

#include <vector>
#include <iostream>

int main() {
    using std::vector;

    vector<int> a = {1, 2, 3};
    vector<int> b = std::move(a); 
    if(a.data() == nullptr) // This should be true now
        std::cout << "a.data() is null now\n"; 
    if(a.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}

В моей системе, используя gcc и clang, этот код печатает

a.data() is null now
a.size() is zero now

Это применимо, даже если у вас есть класс-оболочка:

#include <vector>
#include <iostream>

template<class T>
class Wrapper {
   public:
    // Because all the members of Wrapper are public,
    // the compiler automatically generates move and copy constructors
    T value; 
};


int main() {
    using std::vector;

    Wrapper<vector<int>> a = {{1, 2, 3}};
    Wrapper<vector<int>> b = std::move(a); 
    // Same output as before
    if(a.value.data() == nullptr)
        std::cout << "a.data() is null now\n"; 
    if(a.value.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}
...