Семантика перемещения для члена std::vector

Я хочу убедиться, что я правильно понимаю это. Я спрашиваю это здесь, так как у меня нет средств, это прописано в явном виде.

Например, у меня есть класс треугольной сетки, который в основном построен следующим образом:

class Mesh
{
public:
    struct Face 
    {
        unsigned int a;
        unsigned int b;
        unsigned int c;
    };
//... 
private:
    std::string            file;
    std::vector<glm::vec3> vertices;
    std::vector<glm::vec3> normals;
    std::vector<glm::vec2> texcoord;
    std::vector<Face>      faces;   
}

Поскольку данные в сетке могут быть довольно большими, я хочу реализовать правильную семантику перемещения. Я полностью понимаю это для типов указателей, но для запуска конструктора rvalue мне нужно использовать перемещение, верно?

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

Mesh::Mesh(Mesh&& other)
: file(std::move(other.file)),
  vertices(std::move(other.vertices)),
  normals(std::move(other.normals)),
  texcoord(std::move(other.texcoord)),
  faces(std::move(other.faces) {}

Примечание. Прежде чем кто-то укажет на очевидное, приложение во многих местах использует share_ptr. Но я не хочу искусственно ограничивать использование класса.


person rioki    schedule 14.10.2013    source источник
comment
Я думаю, вы поняли это правильно, ваш код выглядит хорошо для меня. (За исключением отсутствующей закрывающей скобки, но я думаю, что это ошибка копирования/вставки, верно?)   -  person Daniel Frey    schedule 14.10.2013
comment
Обратите внимание, что сгенерированный компилятором или конструктор перемещения по умолчанию сделает это за вас.   -  person juanchopanza    schedule 14.10.2013
comment
glm::vec3, glm::vec2 что такое? Если это классы, то они также должны реализовывать семантику перемещения.   -  person Jagannath    schedule 14.10.2013
comment
@Jagannath Это не имеет значения, поскольку сам vector перемещается, это означает, что элементы вообще не копируются и не перемещаются.   -  person Daniel Frey    schedule 14.10.2013
comment
@Джаганнатх Почему? Перемещение всего std::vector просто передаст право собственности на внутренний буфер. Конечно, они выиграют от этого при изменении размера векторов, но это не обязательно для собственного движка Mesh.   -  person Angew is no longer proud of SO    schedule 14.10.2013
comment
Хорошо, тогда я ошибся. Спасибо за разъяснения.   -  person Jagannath    schedule 14.10.2013


Ответы (1)


Да, вы должны использовать std::move() в конструкторе перемещения, как и вы. Однако ваш конструктор перемещения точно дублирует конструктор по умолчанию. Если ваш класс не определяет ни одного из:

  • конструктор копирования
  • оператор присваивания копии
  • оператор присваивания перемещения
  • деструктор

тогда для вас будет сгенерирован конструктор перемещения по умолчанию, делающий именно то, что вы сделали. Вам лучше отказаться от определения и полагаться на определение по умолчанию.

Даже если ваш класс определяет что-то из вышеперечисленного, вы можете попросить компилятор сгенерировать конструктор перемещения по умолчанию:

class Mesh
{
public:
  Mesh(Mesh &&) = default;
  // the rest as before
};

Таким образом, вам не нужно его определять, и он будет работать, даже если вы позже добавите другие элементы (без риска забыть добавить их в конструктор перемещения вручную).


К сожалению, ни одно из вышеперечисленных действий не применимо к Visual Studio 2015 или более ранней версии, которая не может создавать конструкторы перемещения по умолчанию и не поддерживает = default для операций перемещения. Так что, если вы нацелились на VS ‹= 2015, вам нужно написать конструктор перемещения вручную, как вы это делали.

person Angew is no longer proud of SO    schedule 14.10.2013
comment
Я очень ценю четкий ответ здесь, а также информацию об использовании версий по умолчанию с ключевым словом по умолчанию. Спасибо! - person Benjamin R; 14.04.2015