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

时间:2015-03-09 10:42:23

标签: c++ c++11 move-semantics

似乎我无法完全理解移动语义:我想从外部函数填充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 */.
}

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

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

2 个答案:

答案 0 :(得分:6)

为什么代码有效:

vec的范围是fillVector的主体。在整个范围内,vec完全有效。这包括致电setVectorvsetVector的参数)是绑定到vec的引用。 setVector 的正文将向量vec(作为v访问)的内容复制v_。这是一个实际的数据副本,没有参考分配。仅在setVector结束后fillVector结束,此时vec被销毁。但它已被复制,所以一切都很好。

如何使用移动语义:

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

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

然后, vec移至setVector

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

这将调用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 */.
}

答案 1 :(得分:1)

vector :: operator =指定内容,并且不会链接到现有项目。当你执行v_ = v时,v_获取v中所有内容的新副本。一旦v被销毁,v_中的项目仍然存在。

测试此功能并查看此操作的简单方法是更改​​v_ [i]中的某个项目,然后查看打印出v [i]和v_ [i]。他们将是不同的。

我没有看到你的setVector和fillVector的实现有什么问题。你有什么特别想要实现的目标吗?