简体   繁体   English

为什么要使用move构造函数?

[英]why use a move constructor?

I'm a little confused as to why you would use/need a move constructor. 对于您为什么要使用/需要移动构造函数,我有些困惑。
If I have the following: 如果我有以下内容:

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

I can remove the need to return res, hence not calling the copy constructor, by adding vector fill(istream& is, vector& res) . 我可以通过添加vector fill(istream& is, vector& res)来消除返回res的需要,因此不必调用copy构造函数。

So what is the point of having a move constructor? 那么拥有move构造函数有什么意义呢?

Assume you next put you std::vector<T> into a std::vector<std::vector<T>> (if you think vectors shouldn't be nested, assume the inner type to be std::string and assume we are discussing std::string 's move constructor): even though you can add an empty object and fill it in-place, eventually the vector will need to be relocated upon resizing at which point moving the elements comes in handy. 假设您接下来将std::vector<T>放入std::vector<std::vector<T>> (如果您认为向量不应该嵌套,则假定内部类型为std::string并假设我们正在讨论std::string的move构造函数):即使您可以添加一个空对象并就地填充它,最终向量也需要在调整大小时重新定位,这时移动元素便会派上用场。

Note that returning from a function isn't the main motivator of move construction, at least, not with respect to efficiency: where efficiency matters structuring the code to enable copy-elision further improves performance by even avoiding the move. 请注意,从函数返回并不是移动构造的主要动力,至少不是在效率方面:在效率很重要的情况下,结构化代码以启用复制删除功能甚至可以通过避免移动来进一步提高性能。

The move constructor may still be relevant semantically, though, because returning requires that a type is either copyable or movable. 但是,由于在返回时要求类型是可复制的或可移动的,因此move构造函数在语义上仍可能是相关的。 Some types, eg, streams, are not copyable but they are movable and can be returned that way. 某些类型(例如流)是不可复制的,但它们是可移动的,可以通过这种方式返回。

In you example compiler might apply RVO - Return Value Optimization, this means you function will be inlined, so no return will take place - and no move semantics will be applied. 在您的示例中,编译器可能会应用RVO-返回值优化,这意味着您将内联函数,因此不会发生返回-并且不会应用移动语义。 Only if it cannot apply RVO - move constructor will be used (if available). 仅当它不能应用RVO时,将使用move构造函数(如果可用)。

Before move semantics were introduced people were using various techniques to simulate them. 在引入移动语义之前,人们使用各种技术来模拟它们。 One of them is actually returning values by references. 其中之一实际上是通过引用返回值。

One reason is that using assignment operators makes it easier to grasp what each line is doing. 原因之一是使用赋值运算符可以更轻松地掌握每行的内容。 If have a function call somefunction(var1, var2, var3) , it is not clear whether some of them gets modified or not. 如果有一个调用somefunction(var1, var2, var3)的函数,则不清楚其中是否有人被修改。 To find that out, you have to actually read the other function. 为了找出答案,您必须实际阅读其他功能。

Additionally, if you have to pass a vector as an argument to fill() , it means every place that calls your function will require two lines instead of one: First to create an empty vector, and then to call fill() . 另外,如果必须将向量作为参数传递给fill() ,则意味着调用函数的每个位置都将需要两行而不是一行:首先创建一个空向量,然后调用fill()

Another reason is that a move constructor allows the function to return an instance of a class that does not have a default constructor. 另一个原因是,移动构造函数允许函数返回没有默认构造函数的类的实例。 Consider the following example: 考虑以下示例:

struct something{
    something(int i) : value(i) {}
    something(const something& a) : value(a.value) {}

    int value;
};

something function1(){
    return something(1);
}

void function2(something& other){
    other.value = 2;
}

int main(void){
    // valid usage
    something var1(18);
    // (do something with var1 and then re-use the variable)
    var1 = function1();

    // compile error
    something var2;
    function2(var2);
}

In case you are concerned about effiency, it should not matter whether you write your fill() to return a value, or to take output variable as a parameter. 如果您担心效率问题,那么无论您编写fill()返回值还是将输出变量作为参数,都无关紧要。 Your compiler should optimize it to the most efficient alternative of those two. 您的编译器应将其优化为这两个中最有效的替代方案。 If you suspect it doesn't, you had better measure it. 如果您怀疑不是,则最好对其进行度量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM