命名右值引用

Named rvalue references

请原谅我在这个话题上不够清晰。我正在尝试创建用于将大 class 插入向量的函数。在这个例子中,我使用整数向量作为大 class.

#include <vector>
#include <iostream>
using namespace std;

vector<vector<int>> vectorOfVectors;

void fn(const vector<int> &v) {
    vectorOfVectors.push_back(v);

}
void fn(vector<int> &&v) {
    vectorOfVectors.push_back(std::move(v));
}

int main() {
    vector<int> a({1});
    const vector<int> b({2});
    fn(std::move(a));
    fn(b);
    cout<<b[0];
}

显然,我希望尽可能不进行复制。我的问题:

  1. 这段代码做对了吗?
  2. 有更好的方法吗?
  3. 对于使用自定义 classes 的相同方法,我是否需要定义移动构造函数?

Does this code do the right thing?

是的。 C++11 正是出于这个原因添加了 std::vector::push_back(T&&)

Is there a better way of doing this?

你的 fn(const vector<int> &v)fn(vector<int> &&v) 都在做同样的事情,将参数 v 推到 vectorOfVectors 的末尾。您可以使用一个使用完美转发的函数模板来代替您的两个 fn 函数。

template<typename T>
void fn(T &&v) {
    vectorOfVectors.push_back(std::forward<T>(v));
}

这要归功于 C++11 reference collapsing rulesstd::forward。在 v 是左值的情况下,模板类型 T 变为 vector<int>&,而在 v 是右值的情况下,模板类型 vector<int>&& 变为 vector<int>&。引用折叠规则意味着 vector<int>& && 变为 vector<int>&vector<int>&& && 变为 vector<int>&&。这正是你想要的,调用 push_back 的版本,在左值的情况下执行复制,而在右值的情况下调用移动的版本。

一个缺点是,当您出错时,这有时会导致有趣的诊断。 ("Interesting" 这里表示来自 g++ 或 clang++ 的数百行高深莫测的诊断文本)。另一个缺点是模板可能导致 "converters gone wild".

的情况

For the same approach to work with custom classes, do I need to define move constructors?

不一定。如果 class 没有声明用户定义的析构函数、复制构造函数、复制赋值运算符或移动赋值运算符,您将获得一个隐式声明的移动构造函数。如果 class 具有不可移动的数据成员或派生自无法移动或删除的 class,则隐式声明的移动构造函数将被定义为已删除。

对我来说,这有点太难记了。我不知道这是一个好习惯还是一个坏习惯,但我已经开始使用 Foo(const Foo&)=default,对五个函数的其他规则使用类似的声明。在许多情况下,我还将构造函数限定为 explicit 以避免 "converters gone wild" 问题。

  1. 它确实避免了复制 a
  2. 是的。使用 push_back 意味着您必须至少构造两个对象,而 emplace_back 和完美转发可以做更少的工作。

    template<typename... Ts>
    auto fn(Ts &&...ts)
      -> decltype(vectorOfVectors.emplace_back(std::forward<Ts>(ts)...), void())
    {
        vectorOfVectors.emplace_back(std::forward<Ts>(ts)...);
    }
    

    http://melpon.org/wandbox/permlink/sT65g3sDxHI0ZZhZ

3。只要您使用 push_back,您就需要 类 可移动构造以避免复制。如果您可以获得默认定义,则不一定需要自己定义移动构造函数。