为什么从NRVO中排除了按值参数? [英] Why are by-value parameters excluded from NRVO?

查看:87
本文介绍了为什么从NRVO中排除了按值参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下:

S f(S a) {
  return a;
}

为什么不允许别名 code>和返回值槽?

Why is it not allowed to alias a and the return value slot?

S s = f(t);
S s = t; // can't generally transform it to this :(

规范不允许这种转换if S 的复制构造函数有副作用,而需要至少两个副本(一个从 t a ,一个从 a 到返回值,另一个从返回值到 s ,并且只有最后一个可以省略。注意,我写上 = t 代表 t 到f的 a ,唯一的副本,在移动/复制构造函数的副作用的存在下仍然是强制性的)。

The spec doesn't allow this transformation if the copy constructor of S has side effects. Instead, it requires at least two copies (one from t to a, and one from a to the return value, and another from the return value to s, and only that last one can be elided. Note that I wrote = t above to represent the fact of a copy of t to f's a, the only copy which would still be mandatory in the presence of side effects of move/copy constructor).

为什么呢?

推荐答案

这里是为什么copy elision没有意义

Here's why copy elision doesn't make sense for parameters. It's really about the implementation of the concept at the compiler level.

复制elision通过原地构造返回值来实现,该值不是复制出来的;它直接在其预期目的地创建。这是调用者为预期的输出提供空间,因此它最终是调用者提供了检测的可能性。

Copy elision works by essentially constructing the return value in-place. The value isn't copied out; it's created directly in its intended destination. It's the caller who provides the space for the intended output, and thus it's ultimately the caller who provides the possibility for the elision.

所有的功能内部需要做的为了删除副本,在调用者提供的地方构造输出。如果功能可以做到这一点,你会得到复制精度。如果函数不能,那么它将使用一个或多个临时变量来存储中间结果,然后将其复制/移动到调用者提供的位置。它仍然构建在原地,但是输出的构造通过副本进行。

All that the function internally needs to do in order to elide the copy is construct the output in the place provided by the caller. If the function can do this, you get copy elision. If the function can't, then it will use one or more temporary variables to store the intermediate results, then copy/move this into the place provided by the caller. It's still constructed in-place, but the construction of the output happens via copy.

因此,在特定函数之外的世界不必知道或关心是否一个功能确实。具体来说,函数的调用者不必知道函数的实现方式。它没有什么不同;它是函数本身决定是否可以检测。

So the world outside of a particular function doesn't have to know or care about whether a function does elision. Specifically, the caller of the function doesn't have to know about how the function is implemented. It's not doing anything different; it's the function itself that decides if elision is possible.

值参数的存储也由调用者提供。当调用 f(t)时,调用者创建 t 的副本并将其传递给 f 。类似地,如果 S 可以从 int 隐式构造,则 f(5) code>将从5构造 S ,并将其传递给 f

Storage for value parameters is also provided by the caller. When you call f(t), it is the caller that creates the copy of t and passes it to f. Similarly, if S is implicitly constructable from an int, then f(5) will construct an S from the 5 and pass it to f.

这一切都由调用者完成。被调用者不知道或不在乎它是一个变量还是临时的;它只是给一个堆栈存储器(或寄存器或任何)。

This is all done by the caller. The callee doesn't know or care that it was a variable or a temporary; it's just given a spot of stack memory (or registers or whatever).

现在记住:复制elision工程,因为被调用的函数构造变量直接到输出位置。因此,如果你想从一个值参数中删除返回值,那么值参数的存储器也必须是输出存储器本身。但请记住:调用者为参数和输出提供了存储。因此,要舍弃输出副本,调用者必须直接在输出中构造参数。

Now remember: copy elision works because the function being called constructs the variable directly into the output location. So if you're trying to elide the return from a value parameter, then the storage for the value parameter must also be the output storage itself. But remember: it is the caller that provides that storage for both the parameter and the output. And therefore, to elide the output copy, the caller must construct the parameter directly into the output.

To这样,现在调用者需要知道它调用的函数将会舍弃返回值,因为如果参数将被返回,它只能将参数直接粘贴到输出中。这在编译器级别一般是不可能的,因为调用者不一定具有函数的实现。如果函数是内联的,那么也许它可以工作。

To do this, now the caller needs to know that the function it's calling will elide the return value, because it can only stick the parameter directly into the output if the parameter will be returned. That's not going to generally be possible at the compiler level, because the caller doesn't necessarily have the implementation of the function. If the function is inlined, then maybe it can work. But otherwise no.

因此,C ++委员会并没有考虑这种可能性。

Therefore, the C++ committee didn't bother to allow for the possibility.

这篇关于为什么从NRVO中排除了按值参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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