为什么要使用移动构造函数?

时间:2015-12-02 09:27:59

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

我有点困惑为什么你会使用/需要一个移动构造函数 如果我有以下内容:

vector fill(istream& is)
{
    vector res;
    for(double x; is >> x; res.push_back(x));
    return res;
}

void bar()
{
    vector vec = fill(cin);
    // ... use vec ...
}

我可以通过添加vector fill(istream& is, vector& res)来删除返回res的需要,因此不会调用复制构造函数。

那么有一个移动构造函数是什么意思?

3 个答案:

答案 0 :(得分:4)

假设您接下来将std::vector<T>放入std::vector<std::vector<T>>(如果您认为矢量不应该嵌套,假设内部类型为std::string并假设我们正在讨论{ {1}}移动构造函数):即使你可以添加一个空对象并在原地填充它,最终在调整大小时需要重新定位向量,此时移动元素派上用场。

请注意,从函数返回并不是移动构造的主要动力,至少不是效率:效率很重要,构造代码以使复制省略甚至避免移动,从而进一步提高性能。

但是,移动构造函数在语义上仍然可能是相关的,因为返回要求类型是可复制的或可移动的。某些类型(例如流)不可复制,但它们是可移动的,可以通过这种方式返回。

答案 1 :(得分:2)

在您的示例中,编译器可能会应用RVO - 返回值优化,这意味着您的函数将被内联,因此不会发生任何返回 - 并且不会应用任何移动语义。只有当它不能应用RVO时 - 才会使用移动构造函数(如果可用)。

在引入移动语义之前,人们正在使用各种技术来模拟它们。其中一个实际上是通过引用返回值。

答案 2 :(得分:2)

一个原因是使用赋值运算符可以更容易地掌握每条线的作用。如果有函数调用OnFailure,则不清楚其中一些是否被修改。要找到它,你必须实际阅读其他功能。

此外,如果必须将向量作为参数传递给somefunction(var1, var2, var3),则意味着调用函数的每个位置都需要两行而不是一行:首先创建一个空向量,然后调用{ {1}}。

另一个原因是移动构造函数允许函数返回没有默认构造函数的类的实例。请考虑以下示例:

fill()

如果您担心效率,您是否编写fill()来返回值或将输出变量作为参数都无关紧要。您的编译器应该将其优化为这两者中最有效的替代方案。如果你怀疑它没有,你最好测量一下。