使用左值映射移动位置

Map moving emplace with lvalue

我不确定我是否理解正确这段代码:

template<typename M>
void add(M& m,int i, std::string s)
{
  m.emplace(i,std::move(s));
}

int main()
{
  std::map<int,std::string> m;
  add(m,1,"foo");
}

调用add时,会复制std::stringint。方法 emplace 构造一个 std::pair ,它被移入 std::map (不需要复制)。但是 int 的副本是左值,而 std::string 的副本被转换为右值,因此调用哪个构造函数来构造 std::pair?由于无法移动一个参数,我想这里会发生一个额外的副本。这样对吗?显然,如果我也将 int 的副本转换为右值,我希望不会有额外的副本。

此构造函数调用:

template< class U1, class U2 >
pair( U1&& x, U2&& y );

在这种情况下,xy 不是右值引用而是通用引用。长话短说,由于您的 std::move(),左值(在本例中为 int)折叠为左值引用,右值(在本例中为 std::string)折叠为右值引用。

实例化的构造函数如下所示:

pair( int& x, std::string&& y );

Scott Meyers 解释得更好https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

When add is called, the std::string and the int are copied.

复制了int,但没有要复制的首字母std::string。相反,s 是根据您传入的字符串文字在函数本身中就地构造的。

therefore which constructor is called to construct the std::pair

我们可以混搭。 std::pair:

有一个转发引用构造函数模板
template< class U1, class U2 >
pair( U1&& x, U2&& y );           // since C++11, until C++14

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y ); // since C++14

所以在这种情况下,我们调用 pair<int&, std::string>。没有"additional copy"。