C ++ 11 rvalues和move语义混乱(return statement) [英] C++11 rvalues and move semantics confusion (return statement)

查看:161
本文介绍了C ++ 11 rvalues和move语义混乱(return statement)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解右值引用和C ++ 11的移动语义。

I'm trying to understand rvalue references and move semantics of C++11.

这些例子有什么区别,没有向量复制?

What is the difference between these examples, and which of them is going to do no vector copy?

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> &&rval_ref = return_vector();



第二个例子



Second example

std::vector<int>&& return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();



第三个例子



Third example

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();


推荐答案

第一个例子



First example

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> &&rval_ref = return_vector();

第一个示例返回一个被 rval_ref 。该临时将会使其生命延伸超出 rval_ref 定义,你可以使用它,如果你已经捕获它的值。这非常类似于以下:

The first example returns a temporary which is caught by rval_ref. That temporary will have its life extended beyond the rval_ref definition and you can use it as if you had caught it by value. This is very similar to the following:

const std::vector<int>& rval_ref = return_vector();

除了在我的重写你显然不能以非const方式使用rval_ref。 p>

第二个例子



except that in my rewrite you obviously can't use rval_ref in a non-const manner.

std::vector<int>&& return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

在第二个示例中,您创建了一个运行时错误。 rval_ref现在保存对函数内的已破坏的tmp的引用。任何运气,此代码将立即崩溃。

In the second example you have created a run time error. rval_ref now holds a reference to the destructed tmp inside the function. With any luck, this code would immediately crash.

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

你的第三个例子大致相当于你的第一个例子。 tmp上的std :: move是不必要的,实际上可以是一个性能优化,因为它会抑制返回值优化。

Your third example is roughly equivalent to your first. The std::move on tmp is unnecessary and can actually be a performance pessimization as it will inhibit return value optimization.

编写你正在做的事情的最好方法是:

The best way to code what you're doing is:

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> rval_ref = return_vector();

就像你在C ++ 03中一样。 tmp在return语句中被隐式处理为rvalue。它将通过返回值优化(没有复制,没有移动)返回,或者如果编译器决定它不能执行RVO,那么它将使用向量的移动构造函数做返回。只有没有执行RVO,并且如果返回的类型没有move构造函数,那么复制构造函数将用于返回。

I.e. just as you would in C++03. tmp is implicitly treated as an rvalue in the return statement. It will either be returned via return-value-optimization (no copy, no move), or if the compiler decides it can not perform RVO, then it will use vector's move constructor to do the return. Only if RVO is not performed, and if the returned type did not have a move constructor would the copy constructor be used for the return.

这篇关于C ++ 11 rvalues和move语义混乱(return statement)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆