保证复印精度如何工作? [英] How does guaranteed copy elision work?

查看:104
本文介绍了保证复印精度如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在2016年Oulu ISO C ++标准会议上,提案名为保证复制Elision 被标准委员会投票选为C ++ 17。

At the 2016 Oulu ISO C++ Standards meeting, a proposal called Guaranteed Copy Elision was voted into C++17 by the standards committee.

它是如何工作的?

推荐答案

复制elision已被允许,或者是否需要更改代码以保证复制elision?允许在多种情况下发生。然而,即使它被允许,代码仍然必须能够工作,好像副本没有被省略。也就是说,必须有一个可访问的副本和/或移动构造函数。

Copy elision was permitted to happen under a number of circumstances. However, even if it was permitted, the code still had to be able to work as if the copy were not elided. Namely, there had to be an accessible copy and/or move constructor.

保证复制精度只是说明了一些情况,其中不再需要是可访问的副本/ move构造函数。

Guaranteed copy elision simply spells out a number of circumstances where there no longer has to be an accessible copy/move constructor. That is, the code is guaranteed to elide the copy operation.

考虑这个函数:

T Func() {return T();}

复制elision规则,这将创建一个临时的,然后从该临时变换到函数的返回值。该移动操作可以被省略,但 T 必须仍然具有可访问的移动构造函数,即使它从未使用。

Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.

类似地:

T t = Func();

这是 t 的复制初始化。这将复制初始化 t ,返回值 Func 。但是, T 仍然必须有一个移动构造函数,即使它不会被调用。

This is copy initialization of t. This will copy initialize t with the return value of Func. However, T still has to have a move constructor, even though it will not be called.

说,在这两种情况(和其他几种情况)下,复制/移动操作的检测是确定的。因此, T 不需要复制/移动构造函数。

Guaranteed copy elision says that in these two circumstances (and several others), the elision of the copy/move operation is certain. And therefore, T need not have copy/move constructors.

这允许你做的一件事是返回对象其是不可移动的。例如, lock_guard 无法复制或移动,因此您不能有一个按值返回它的函数。但是有了保证复制的精确度,你可以。

One thing this permits you to do is return objects which are immobile. For example, lock_guard cannot be copied or moved, so you couldn't have a function that returned it by value. But with guaranteed copy elision, you can.

只要你遵循规则。一般的想法是,一个prvalue表达式不是一个临时的;它是一个对象的初始化器。如果使用prvalue的表达式用作与prvalue具有相同类型的对象的初始化器,那么它将直接初始化它,而不会复制或移动。因此,类型不需要具有可访问的复制/移动构造函数。

So long as you follow the rules. The general idea is that a prvalue expression is not a temporary; it is an initializer for an object. If the expression that uses a prvalue is used as an initializer for an object of the same type as the prvalue, then it initializes it directly, without copying or moving. And therefore, the type does not need to have an accessible copy/move constructor.

如果以任何其他方式使用prvalue,则prvalue将初始化一个临时变量将在该表达式中使用(或如果没有表达式则被丢弃)。

If a prvalue is used in any other way, the prvalue will initialize a temporary, which will be used in that expression (or discarded if there is no expression).

因此,如果初始化函数的返回值,其他函数,则没有复制的返回值;它只是直接初始化返回值对象。

So if you initialize the return value of a function with a temporary or the return value of some other function, then there is no copy of the return value; it simply initializes the return value object directly. If you initialize a stack variable with the return value of a function of the same type, then the stack variable is initialized directly.

你甚至可以用这个直接初始化:

You even get direct initialization with this:

new T(FactoryFunction());

如果 FactoryFunction 返回 T ,则此表达式不会将返回值复制到分配的内存中。

If FactoryFunction returns T by value, this expression will not copy the return value into the allocated memory. It will instead allocate memory and use that memory as the return value memory for the function call directly.

因此,返回值的工厂函数可以直接初始化堆分配的内存,甚至不需要重新分配内存。知道它。只要他们内部遵守保证复制的规则。也就是说,它们返回类型为 T 的prvalue。

So factory functions that return by value can directly initialize heap allocated memory without even knowing about it. So long as they internally follow the rules of guaranteed copy elision. That is, they return a prvalue of type T.

当然,这也适用:

new auto(FactoryFunction());

如果您不喜欢撰写类型名称。

In case you don't like writing typenames.

重要的是要认识到上述保证只适用于贬值。也就是说,返回一个命名的变量时,你不能保证:

It is important to recognize that the above guarantees only work for prvalues. That is, you get no guarantee when returning a named variable:

T Func()
{
   T t = ...;
   ...
   return t;
}

在这种情况下, t 仍然必须具有可访问的复制/移动构造函数。是的,编译器可以选择优化离开复制/移动。但是编译器必须仍然验证是否存在可访问的复制/移动构造函数。

In this instance, t must still have an accessible copy/move constructor. Yes, the compiler can choose to optimize away the copy/move. But the compiler must still verify the existence of an accessible copy/move constructor.

因此,命名返回值优化(NRVO)没有任何更改。

So nothing changes for named return value optimization (NRVO).

这篇关于保证复印精度如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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