Недавно я начал изучать семантику перемещения и несколько дней думал о следующей проблеме:
Допустим, у нас есть класс, который нельзя скопировать, например:
class Texture
{
public:
Texture(unsigned int texID);
~Texture();
Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete;
Texture(Texture&& rhs);
Texture& operator=(Texture&& rhs);
// ...
private:
unsigned int mTexID;
};
Для тех, кому интересно, такие классы-обертки часто встречаются при работе с OpenGL.Идентификатор используется для доступа к данным, хранящимся в графическом процессоре, и используется для указания графическому процессору уничтожить указанные данные, что делается в деструкторе этого класса-оболочки.Вот почему это не копируемый класс.
Теперь, допустим, у нас есть еще один не копируемый класс, подобный следующему:
class Mesh
{
public:
// Notice how the constructor receives the vector of Texture objects (a move-only type) by reference
Mesh(const std::vector<unsigned int>& indices, std::vector<Texture>& textures)
: mIndices(indices)
, mTextures(std::move(textures))
{
// ...
}
~Mesh();
Mesh(const Mesh&) = delete;
Mesh& operator=(const Mesh&) = delete;
Mesh(Mesh&& rhs);
Mesh& operator=(Mesh&& rhs);
// ...
private:
std::vector<unsigned int> mIndices;
std::vector<Texture> mTextures;
};
С конструктором, каким он является сейчас,клиент может создать Mesh
, выполнив следующие действия:
std::vector<unsigned int> indices;
std::vector<Texture> textures;
// ...
Mesh mesh(indices, textures); // Client is unaware that the textures vector has been moved from
Мой вопрос: будет ли лучше, если конструктор класса Mesh
будет объявлен так:
// Notice how the constructor receives the vector of Texture objects (a move-only type) by rvalue reference
Mesh::Mesh(const std::vector<unsigned int>& indices, std::vector<Texture>&& textures)
: mIndices(indices)
, mTextures(std::move(textures))
{
// ...
}
С помощью этого нового конструктора клиент будет вынужден делать следующее при создании объекта Mesh
:
std::vector<unsigned int> indices;
std::vector<Texture> textures;
// ...
Mesh mesh(indices, std::move(textures)); // Client is fully aware that the textures vector has been moved from
Это, конечно, больше печатать, но теперь пользователь полностью осознает, что текстурыvector был перемещен из, и я не вижу каких-либо последствий для производительности.
Поэтому я предполагаю, что мой вопрос таков: существуют ли рекомендации относительно того, как лучше всего получать перемещаемые типы, из которых будут перемещаться?Получение по ссылке на const ясно указывает на то, что тип не будет перемещен, так как же поступить наоборот?Как сказать клиенту, что тип будет перемещен?