当我学习 C++11 右值引用和移动语义时,我开始对函数如何返回值来初始化变量感到困惑。看下面的例子:
Widget makeWidget()
{
Widget w;
…
return w;
}
Widget w1 = makeWidget();
这里我假设没有 RVO(即编译不会消除复制/移动)。执行return语句时return w;
,函数执行:
1)在众所周知的位置(调用者知道的某个固定寄存器或内存位置)初始化一个临时对象,其值成为函数的返回值?然后调用者获取这个对象进行复制初始化w1
? Or
2)该函数获取调用者传递的内存位置w1
和函数的自动变量w
用于复制初始化w1
? (这已经是某种 RVO 了吗?或者某种内联函数行为?或者它是一种可能的调用约定?)
如果是第一种情况,并且 return 创建一个临时对象,则将有两个复制构造函数调用,一个创建临时对象,一个创建w1
。如果是第二种情况,则只会调用一次复制构造函数来创建w1
.
现在假设我们有 RVO。那么如果return的行为是case1),那么编译器可以通过构造来消除临时的复制构造w
直接在众所周知的位置获取返回值。如果 return 的行为类似于 case2),那么 RVO 在这种情况下甚至可以创建自动变量w
直接位于分配的内存位置w1
。我对RVO的理解正确吗?
现在让我添加移动语义。再次假设没有 RVO,请看以下示例:
Widget makeWidget()
{
Widget w;
…
return std::move(w);
}
Widget w1 = makeWidget();
现在再次针对上面的两种情况:
1)我期望有两个动作吗:第一个动作来自初始化温度Widget
带有表达式的对象std::move(w)
;第二步来自初始化w1
随着温度Widget
哪个是右值?或者
2)只有一招:初始化w1
与表达std::move(w)
?
最后一个问题:返回行为是否取决于它返回的是 POD 类型还是类类型?