【发布时间】:2011-05-15 15:22:11
【问题描述】:
想象一下:
S f(S a) {
return a;
}
为什么不允许别名a和返回值槽?
S s = f(t);
S s = t; // can't generally transform it to this :(
如果S 的复制构造函数有副作用,规范不允许这种转换。相反,它至少需要两份副本(一份从t 到a,一份从a 到返回值,另一份从返回值到s,只有最后一个可以省略。请注意,我在上面写了= t 以表示将t 复制到f 的a 的事实,这是在移动/复制构造函数存在副作用的情况下仍然是强制性的唯一副本。
这是为什么呢?
【问题讨论】:
-
因为原样返回参数不是很有用?
-
@BoP 如果我们更改参数会怎样?
S f(S s) { for(E &e : s) e.toupper(); return s; }。编译器可以执行 NRVO,并忽略return s,因为返回值已经到位。少一份/少搬一份! -
嗯,也许它与调用约定有关?调用者必须知道要在哪个传出参数槽中找到返回值。这似乎与其他允许的 NRVO 形式不同。我想得到一个很好的答案来解释它:)
-
@Matthieu 代码是否内联都没关系。如果副本有副作用并且 NRVO 无法应用(即,可观察到的副作用),则必须始终完成副本。我认为,如果 NRVO 可以适用于我的情况,我会少获得一份。
-
@Bo, @Neil:问题当然不是,“这通常是一个好的/容易的优化吗?”,问题是,“为什么标准包含额外的文本,只是为了禁止这个优化?”。禁止它一定有一个积极的理由,“它不值得做”仅在只是标准忽略允许它的问题时才解释这种情况。
标签: c++ c++11 return-value-optimization