如何改进std :: vector参数传递(移动语义?)

Jav*_*i V 4 c++ move-semantics c++11

似乎我无法完全理解移动语义:我想std::vector从外部函数填充(类的成员).目前,我有类似的东西:

void fillVector(MyClass & myclass) {
    std::vector<int> vec;
    /* Filling vec */
    // ...
    myclass.setVector(vec);
}

class MyClass {
    public:
         setVector(const std::vector<int> & v) { v_ = v;}
    private:
         std::vector<int> v_;
};

int main() {
    MyClass myclass;
    fillVector(myclass);
    /* Use myclass.v_ somehow */.
}
Run Code Online (Sandbox Code Playgroud)

我有这个代码很长一段时间,它工作正常.现在,我无法理解它是如何工作的,因为我将对一个将被销毁的向量的引用作为参考.我的问题是:

  1. 这段代码如何工作?
  2. 什么是实施的最佳方式fillVectorMyClass::setVector()?我认为可以用移动语义完成,但我无法弄清楚如何.

谢谢!

Rei*_*ica 6

为什么代码有效:

范围vec是身体fillVector.在整个范围内,vec完全有效.这包括致电setVector.v(参数setVector)是一个绑定的参考vec.将载体的内容(访问为)setVector 复制到的主体.这是数据的实际副本,没有参考分配.只有在结束后才会结束,此时会被销毁.但它已被复制,所以一切都很好.vecvv_setVectorfillVectorvec

如何使用移动语义:

您可以提供一个额外的重载setVector,它将采用右值引用:

class MyClass {
public:
  // ...
  void setVector(std::vector<int> &&v) { v_ = std::move(v); }
  // ...
};
Run Code Online (Sandbox Code Playgroud)

然后,移动 vecsetVector:

void fillVector(MyClass & myclass) {
    std::vector<int> vec;
    /* Filling vec */
    // ...
    myclass.setVector(std::move(vec));
}
Run Code Online (Sandbox Code Playgroud)

这将调用rvalue重载而不是lvalue重载,数据将被移动,而不是被复制.

但是,也许更好的接口是重构,fillVector以便它按值返回向量,自动使用移动语义:

std::vector<int> fillVector() {
    std::vector<int> vec;
    /* Filling vec */
    // ...
    return vec;  // Note that a move automatically happens here, or even NRVO
}

int main() {
    MyClass myclass;
    myclass.setVector(fillVector());
    /* Use myclass.v_ somehow */.
}
Run Code Online (Sandbox Code Playgroud)

  • @Yakk如果你想保持const引用过载也不行.const引用超载[在左值的情况下可能表现更好](https://www.youtube.com/watch?v=xnqTKD8uD64&t=1h03m44s),因为它可以重复使用`v_`的任何现有容量. (2认同)