简体   繁体   English

为什么for_each通过移动返回功能

[英]Why does for_each return function by move

I was reading the documentation for std::for_each here http://en.cppreference.com/w/cpp/algorithm/for_each and saw that the return value is std::move(f) 我在这里阅读std::for_each的文档http://en.cppreference.com/w/cpp/algorithm/for_each并看到返回值为std::move(f)

Why does the standard enforce moving the input parameter in the return value? 为什么标准强制在返回值中移动输入参数? Won't it be moved by default anyway, since the input parameter is passed by value? 默认情况下不会移动它,因为输入参数是按值传递的吗?


This leads me to a couple of followups, when you compile the following code 当您编译以下代码时,这会引导我进行几次跟进

Something function(Something something) {
    return something;
} 
  1. The return statement is a move on my system with the highest optimization level ( -O3 ), why don't most compilers elide this return value? return语句是我的系统上具有最高优化级别( -O3 )的移动,为什么大多数编译器都不会忽略此返回值? Local values are elided but function arguments are not.. 省略了本地值,但函数参数不是..

  2. Does C++17 enforce elision in this case? 在这种情况下C ++ 17是否强制执行? I read the proposal ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html ) but I do not fully understand which cases qualify for mandatory elision. 我阅读了该提案( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html )但我并不完全了解哪些案例符合强制性省略的条件。

I have tried this on Apple LLVM version 8.0.0 (clang-800.0.42.1) on my Mac and on g++ 5.4 on Ubuntu 16.04. 我在我的Mac上的Apple LLVM version 8.0.0 (clang-800.0.42.1)和Ubuntu 16.04上的g++ 5.4上尝试了这个。

This is due to a late-breaking change in the move-semantics rules for C++11. 这是由于C ++ 11的移动语义规则的最新变化。 The original move proposal did not automatically move when by-value function arguments appeared on the return clause. 当返回子句中出现按值函数参数时, 原始移动提议不会自动移动。 However by late in the C++11 process, that language feature was added. 但是在C ++ 11进程的最后阶段,添加了该语言功能。

Prior to the language feature being added, for_each "was moved". 在添加语言功能之前, for_each “已被移动”。 At that time the move on the return statement was necessary. 那时,返回声明的举动是必要的。 But it became unnecessary, though harmless by the time C++11 shipped. 但是,在C ++ 11出货的时候,它变得毫无必要。

LWG issue 2747 corrected this for C++17. LWG issue 2747为C ++ 17纠正了此问题

As to your first followup question, I am not a compiler writer, but my best guess is: It is not currently legal to elide the return from a function parameter (that much I know), and I'm guessing as to why it isn't legal is that no one has figured out how to implement it, and thus no one has had the motivation to change the standard to make it legal. 关于你的第一个后续问题,我不是编译器编写者,但我最好的猜测是:从功能参数(我知道的很多)中忽略返回目前是不合法的,我猜测为什么它不是合法的是,没有人知道如何实施它,因此没有人有动力改变标准使其合法化。

Second follow up: No, C++17 does not enforce elision in this case. 第二次跟进:不,C ++ 17在这种情况下不强制执行省略。 The rules remain the same as for C++11 in this case, save for the fact that the redundant move from for_each is no longer specified. 在这种情况下,规则与C ++ 11保持相同,除了不再指定从for_each进行冗余移动的事实。

From the comments below: 从下面的评论:

Why do you say it's not legal to elide the return from a function parameter? 为什么你说从函数参数中退出是不合法的?

I'm referencing N4660 , which is C++17, but there is similar wording in C++98/03/11/14 ... backup, it has recently been protected. 我正在引用N4660 ,即C ++ 17,但在C ++ 98/03/11/14备份中有类似的措辞,它最近受到了保护。 See N4659 instead (just as good): 请参阅N4659 (同样好):

15.8.3 Copy/move elision [class.copy.elision] 15.8.3复制/移动省略[class.copy.elision]

  1. When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, ... 当满足某些条件时,允许实现省略类对象的复制/移动构造,......

    • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler (18.3)) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function call's return object 在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象的名称(除了函数参数或由处理程序异常声明引入的变量(18.3))之外相同类型(忽略cv-qualification)作为函数返回类型,通过将自动对象直接构造到函数调用的返回对象中,可以省略复制/移动操作

This language specifically disallows elision from function parameters. 这种语言特别禁止从功能参数中省略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM