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

How to improve std::vector parameter passing (move semantics?)

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

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() 的最佳方法是什么?我认为这可以通过移动语义来完成,但我不知道该怎么做。

谢谢!

为什么代码有效:

vec 的范围是 fillVector 的正文。在整个范围内,vec 是完全有效的。这包括对 setVector 的调用。 vsetVector 的参数)是绑定到 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));
}

这将调用右值重载而不是左值重载,数据将被移动,而不是被复制。

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

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 */.
}

vector::operator= 分配内容,而不仅仅是 link 现有项目。当你执行 v_ = v 时,v_ 会得到 v 中所有内容的新副本。一旦 v 被销毁,v_ 中的项目仍然存在。

一个简单的方法来测试它并查看它的实际效果是更改 v_[i] 中的一项并查看然后打印出 v[i] 和 v_[i]。他们会有所不同。

我没有发现您对 setVector 和 fillVector 的实施有任何问题。您有什么特别想要实现的目标吗?