Why does for_each return function by move

﹥>﹥吖頭↗ 提交于 2019-12-18 15:53:18

问题


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)

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? Local values are elided but function arguments are not..

  2. Does C++17 enforce elision in this case? 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.

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.


回答1:


This is due to a late-breaking change in the move-semantics rules for 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.

Prior to the language feature being added, for_each "was moved". At that time the move on the return statement was necessary. But it became unnecessary, though harmless by the time C++11 shipped.

LWG issue 2747 corrected this for 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. 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.

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. See N4659 instead (just as good):

15.8.3 Copy/move elision [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

This language specifically disallows elision from function parameters.



来源:https://stackoverflow.com/questions/43163801/why-does-for-each-return-function-by-move

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!