用rvalue构造一对

时间:2016-04-19 18:44:51

标签: c++ c++11

在此:

    vector<pair<string,int>> vp;
    string s;
    int i;
    while(cin>>s>>i) vp.push_back({s,i});

我对最后一行感到好奇。该对是在push_back的调用中构建的,因此它被移动,而不是复制,是否正确?

如果它被写成了这样:

    vector<pair<string,int>> vp;
    string s= ...;
    int i= ...;
    pair<string,int> p{s,i};
    vp.push_back(p);

虽然该对的构造涉及相同的资源,但现在该对被命名为p,因此它不再是rvalue,因此不再使用移动语义,因此这是值传递,导致复制,对吗?

这对我来说意味着,在可能的情况下,在arg列表中构建对象是一种性能改进;任何人都可以验证吗?

2 个答案:

答案 0 :(得分:6)

  

该对是在>>> datetime(2016,10,1)-timedelta(1) datetime.datetime(2016, 9, 30, 0, 0) 的调用中构建的,因此它被移动,而不是复制,是否正确?

构造临时对,然后绑定到push_back的右值引用参数。然后将其从该参数移到push_back

vector

相当于:

vp.push_back({s,i});

大致相当于:

vp.push_back(std::pair<std::string, int>{s, i});

你不需要临时使用rvalue引用重载。

您的第二个代码示例:

std::pair<std::string, int> p{s, i};
vp.push_back(std::move(p));

复制而不是移动,是的。请注意,无论哪种方式,我们仍然会将pair<string,int> p{s,i}; vp.push_back(p); 复制到对中(临时或s)。因此,更好的方法是将p移动到临时区域中:

s

或甚至没有开头的中间对:

vp.push_back({std::move(s), i});
  

这对我来说意味着,在可能的情况下,在arg列表中构建对象是一种性能改进;任何人都可以验证吗?

移动是一项性能改进,但您可以始终vp.emplace_back(std::move(s), i); 一个函数的参数 - 它不需要是临时的。在arg列表中构造会影响何时调用move-from对象的析构函数。

答案 1 :(得分:1)

你是对的。

在arg列表中构造对象是一种改进。

但是想一会儿。 int无法移动。这是一份副本。通常std::string会被移动,这样可以安全地进行malloc / new次呼叫。

如果这一切都不影响可读性 - 那就去吧。否则,在大多数情况下,我认为它不会有如此大的改进。

我会建议一个&#34;方式&#34;

std::pair<std::string,int> p{s,i};
vp.push_back(std::move(p));

我建议甚至多一个&#34;方式&#34;

vp.emplace_back(std::move(s), i);

更新 - 我删除了问题中删除的cin部分。