我正在阅读std::for_each
此处http://en.cppreference.com/w/cpp/algorithm/for_each的文档,并看到返回值为std::move(f)
为什么标准强制在返回值中移动输入参数?默认情况下不会移动它,因为输入参数是按值传递的吗?
当您编译以下代码时,这会引导我进行几次跟进
Something function(Something something) {
return something;
}
return语句是我的系统上具有最高优化级别(-O3
)的移动,为什么大多数编译器都不会忽略此返回值?省略了本地值,但函数参数不是..
在这种情况下,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
上尝试了此操作。
答案 0 :(得分:12)
这是由于C ++ 11的移动语义规则的最新变化。当返回子句中出现按值函数参数时,The original move proposal没有自动移动。但是在C ++ 11过程的最后阶段,添加了该语言功能。
在添加语言功能之前,for_each
“已被移动”。那时,返回声明的举动是必要的。但是,在C ++ 11发布的时候,它变得没有必要了,但是它是无害的。
LWG issue 2747为C ++ 17纠正了此问题。
至于你的第一个后续问题,我不是编译器编写者,但我最好的猜测是:从函数参数(我知道的很多)中退出是不合法的,而且我在猜测为什么它不合法是没有人弄清楚如何实施它,因此没有人有动力改变标准使其合法化。
第二次跟进:不,C ++ 17在这种情况下不强制执行。在这种情况下,规则与C ++ 11保持相同,除了不再指定for_each
的冗余移动这一事实。
来自以下评论:
为什么你说从函数参数中退出是不合法的?
我正在引用N4660,这是C ++ 17,但在C ++ 98/03/11/14备份中也有类似的措辞,它最近受到了保护。请改为N4659(同样好):
15.8.3复制/移动elision [class.copy.elision]
- 醇>
当满足某些条件时,允许实现省略类对象的复制/移动构造,...
- 在具有类返回类型的函数中的
中return
语句中,当表达式是非易失性自动对象的名称时(除了函数参数或引入的变量之外)通过处理程序(18.3)的 exception-declaration 与函数返回类型相同的类型(忽略cv-qualification),可以省略复制/移动操作通过将自动对象直接构造到函数调用的返回对象
这种语言明确禁止从功能参数中删除。