[英]Using move semantics with std::pair or std::tuple
假設你想利用移動語義,但你的一個可移動類需要成為std::pair
。 目的是創建一個函數,該函數返回一個std::pair
,可以將其視為rvalue並轉發。
但我無法看到如何做到這一點,除非對std::pair
本身進行內部更改,以使其了解移動語義。
請考慮以下代碼:
struct Foo
{
Foo() { }
Foo(Foo&& f) { }
private:
Foo(const Foo& f) { } // do not allow copying
};
int main()
{
Foo f;
std::pair<Foo, int> res = std::make_pair(f, 10); // fails due to private copy constructor
}
問題是std::make_pair
以及std::pair
構造函數本身需要兩個對象並嘗試制作它們的內部副本。 這導致它嘗試並調用復制構造函數。 但在我的例子中,我希望能夠將新對移動到res
,並確保不會創建副本。 除非std::pair
本身在內部定義了以下構造函數,否則我認為這是不可能的:
pair(T1&& t1, T2&& t2) : first(std::move(t1)), second(std::move(t2))
但它沒有,至少在我使用的編譯器上沒有(gcc 4.3.2)。 這可能是因為我的編譯器是簡單地外的日期,而事實上新版本都會有這樣的舉動感知構造。 但是我對移動語義的理解目前有點不穩定,所以我不確定我是否只是在這里忽略了一些東西。 那么,我是否正在努力實現,而不是實際重新實現std::pair
? 或者我的編譯器是否已過時?
但是,這不是將被調用的std::pair
構造函數。 將調用std::pair
移動構造函數,移動構造函數應該完全符合您的預期(N3126 20.3.5.2/6):
template<class U, class V> pair(pair<U, V>&& p);
效果:構造函數首先使用
std::move(p.first)
初始化,然后使用std::move(p.second)
第二次初始化。
但是,您的示例應該失敗,因為在std::make_pair(f, 10);
, f
是左值,需要明確move
d,否則復制。 以下應該有效:
std::pair<Foo, int> res = std::make_pair(std::move(f), 10);
GCC 4.3.2必須沒有完整的實施。 pair(和tuple)應該有移動構造函數:
template<class U, class V> pair(U&& x, V&& y);
效果:構造函數首先使用std :: forward(x)進行初始化,然后使用std :: forward(y)進行第二次初始化。
template<class U, class V> pair(pair<U, V>&& p);
效果:構造函數首先使用std :: move(p.first)進行初始化,然后使用std :: move(p.second)進行第二次初始化。
(來自n3126中的[pairs.pair])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.