[英]Should a constructor for a class that contains a move-only type receive the move-only type by reference or by rvalue reference?
我最近開始學習移動語義,幾天后我一直在考慮以下問題:
假設我們有一個不可復制的類,如下所示:
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時通常會有這樣的包裝類。 該ID用於訪問存儲在GPU中的數據,它用於告訴GPU銷毀所述數據,這是在此包裝類的析構函數中完成的。 這就是為什么它是一個不可復制的類。
現在讓我們說我們有另一個不可復制的類,如下所示:
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
它肯定更多的打字,但現在用戶完全意識到紋理矢量已被移除,我沒有看到任何性能影響。
所以我想我的問題是:是否有關於接收僅移動類型的最佳方法的指導原則是什么? 通過引用接收清楚地表明該類型不會被移動,那么如何做相反的事情呢? 如何告訴客戶端類型將被移出?
如果傳遞的值可能是prvalue,那么使用rvalue引用顯然更好:
struct A {};
struct B {B(A&);};
struct C {C(A&&);};
A get();
A a;
B b{a}; // OK: a is an lvalue
B b2{get()}; // error: prvalue
C c{a}; // error: lvalue
C c2{std::move(a)}; // OK: xvalue
C c3{get()}; // OK: prvalue
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.