为什么for_each通过move返回函数 [英] Why does for_each return function by move

查看:106
本文介绍了为什么for_each通过move返回函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里 http://en.cppreference中阅读了std::for_each的文档. com/w/cpp/algorithm/for_each ,发现返回值为std::move(f)

为什么标准强制将输入参数移动到返回值中?由于输入参数是通过值传递的,因此默认情况下还是不会移动它吗?


当您编译以下代码时,这将导致一些后续操作

Something function(Something something) {
    return something;
} 

  1. return语句是我的系统上具有最高优化级别(-O3)的动作,为什么大多数编译器都不会忽略此返回值?

  2. 在这种情况下,C ++ 17是否强制执行省略?我阅读了提案( http://www. open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html ),但我不完全了解哪些情况符合强制淘汰的条件.

我已经在Mac上的Apple LLVM version 8.0.0 (clang-800.0.42.1)和Ubuntu 16.04的g++ 5.4上尝试过此操作.

解决方案

这是由于C ++ 11的移动语义规则的最新更改所致. 原始举动提案不会自动当按值函数参数出现在return子句上时移动.但是,到C ++ 11流程的后期,才添加了该语言功能.

在添加语言功能之前,for_each已移动".当时有必要继续执行return语句.但这变得不必要了,尽管在C ++ 11发行时已经无害了.

LWG问题2747 已针对C ++ 17进行了纠正. /p>

关于您的第一个后续问题,我不是编译器作者,但我最大的猜测是:从函数参数中取消返回值(据我所知)目前不合法,我正在猜测之所以不合法,是因为没有人知道如何实施它,因此也没有人愿意改变标准使其合法.

第二次跟进:否,在这种情况下C ++ 17不会强制省略.在这种情况下,规则仍然与C ++ 11相同,除了不再指定从for_each开始的多余移动.

从下面的评论中:

为什么您说从函数参数中取消返回值是不合法的?

我引用的是 N4660 ,这是C ++ 17,但是在C ++ 98/03/11/14中有类似的措辞...备份,它最近受到了保护.请参见 N4659 (效果很好):

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

  1. 当满足某些条件时,允许实现省略类对象的复制/移动构造,...

      expression 是非易失性自动对象的名称(函数参数或由变量引入的变量除外)中的类返回类型的函数中的语句中的
    • handler (18.3)的 exception-declaration 与函数返回类型具有相同类型(忽略cv限定),可以通过构造来省略复制/移动操作将自动对象直接放入函数调用的返回对象中

这种语言专门禁止省略函数参数.

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.

解决方案

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.

这篇关于为什么for_each通过move返回函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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