使用std :: pair或std :: tuple的移动语义

Cha*_*l72 20 c++ move-constructor move-semantics c++11 std-pair

假设你想利用移动语义,但你的一个可移动类需要成为一部分std::pair.目的是创建一个函数,该函数返回一个std::pair可被视为右值并转发的函数.

但我无法看到如何做到这一点,除非对其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
}
Run Code Online (Sandbox Code Playgroud)

问题是std::make_pair,除了std::pair构造函数本身之外,还需要两个对象并尝试制作它们的内部副本.这导致它尝试并调用复制构造函数.但在我的例子中,我希望能够新对移动res,并确保不会制作副本.我认为除非std::pair自己在内部定义了以下构造函数,否则这是不可能的:

pair(T1&& t1, T2&& t2) : first(std::move(t1)), second(std::move(t2))
Run Code Online (Sandbox Code Playgroud)

但它没有,至少在我使用的编译器上没有(gcc 4.3.2).这可能是因为我的编译器是简单地外的日期,而事实上新版本拥有这一举动感知构造.但是我对移动语义的理解目前有点不稳定,所以我不确定我是否只是在这里忽略了一些东西.那么,我是否正在努力实现,而不是实际重新实现std::pair?或者我的编译器是否已过时?

Jam*_*lis 19

但是,这不是std::pair将被调用的构造函数.该std::pair移动构造函数将被调用,而移动构造函数应该做的正是你所期望的(N3126 20.3.5.2/6):

template<class U, class V> pair(pair<U, V>&& p);
Run Code Online (Sandbox Code Playgroud)

效果:构造函数首先使用std::move(p.first)和第二个初始化std::move(p.second).

然而,你的榜样应该失败,因为std::make_pair(f, 10);,f是一个左值,需要明确moveð,否则将被复制.以下应该有效:

std::pair<Foo, int> res = std::make_pair(std::move(f), 10);
Run Code Online (Sandbox Code Playgroud)