假设您想要利用移动语义,但您的一个可移动类需要成为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
}
问题是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
?或者我的编译器是否过时了?
答案 0 :(得分:18)
但这不是将被调用的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);
答案 1 :(得分:2)
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])