return语句是否为按函数返回的函数创建临时对象?

时间:2015-09-05 05:46:03

标签: c++ c++11

当我正在学习C ++ 11 rvalue引用并移动语义时,我开始对函数如何返回一个值来初始化变量感到困惑。请看以下示例:

Widget makeWidget()
{
    Widget w;
    …
    return w;
}
Widget w1 = makeWidget();

这里我假设没有RVO(即编译不会复制/移动)。执行return语句return w;时,执行函数:

1)复制初始化一个临时对象,其值成为函数的返回值,在一个众所周知的位置(一些固定的寄存器或调用者知道的内存位置)?然后调用者提取此对象以复制初始化w1?或者

2)该函数获取调用者传递的内存位置w1,函数的自动变量w用于复制初始化{{1} }? (这是某种类型的RVO吗?还是某种内联函数行为?或者它是一种可能的调用约定?)

如果是第一种情况,并且return创建一个临时的,则会有两个复制构造函数调用,一个创建临时调用,一个创建w1。如果是第二种情况,则只有一个复制构造函数调用来创建w1

现在假设我们有RVO。然后,如果return的行为是case 1),那么编译器可以通过直接在众所周知的位置构造w1来获得返回值,从而忽略临时的复制结构。如果返回的行为类似于 2),那么在这种情况下,RVO甚至可以直接在为w分配的内存位置创建自动变量w。我对RVO的理解是否正确?

现在让我添加移动语义。再次假设没有RVO,请看下面的例子:

w1

现在再次针对上述两种情况:

1)我预计会有两个动作:第一步来自初始化带有表达式Widget makeWidget() { Widget w; … return std::move(w); } Widget w1 = makeWidget(); 的临时Widget对象;第二步是使用临时值std::move(w)初始化w1? OR

2)只有一个步骤:使用表达式Widget初始化w1

最后一个问题:返回行为是否取决于它是返回POD类型还是类类型?

1 个答案:

答案 0 :(得分:6)

  

1)复制初始化一个临时对象,其值变为   函数的返回值,在一个众所周知的位置(一些固定的寄存器   或来电者知道的内存位置)?然后调用者获取此对象   复制初始化w1?

大概这个。通常,调用者分配必要的堆栈空间来保存返回值,并将指针作为隐藏参数传递给它。

请注意,两个复制初始化实际上都是移动。

  

然后编译器可以忽略临时的构造   直接在众所周知的位置构建w以获得返回值。

对(但这是一个举动)。并且它可以通过将其地址作为应该构造返回值的位置来进一步忽略w1的构造。

Widget makeWidget()
{
    Widget w;
    …
    return std::move(w);
}
Widget w1 = makeWidget();

这是一个不可移动的行动(从std::move(w)到临时返回值)和一个可移动的移动(从临时返回值到w1)。

  

返回行为取决于它是返回POD类型还是返回   班级类型?

它可以。根据平台ABI,可以在寄存器中返回一些小的POD类型。