提问人:Petr 提问时间:10/8/2023 最后编辑:Peter CordesPetr 更新时间:10/9/2023 访问量:101
C++ 是否/可以优化对函数参数的调用?
Does/can C++ optimize away call to a function argument?
问:
让我们假设这个函数模板:
template <typename F>
void foo(F&& f) {
f("foo");
}
void to_optimize() {
foo([](std::string_view s) {
std::cout << s << std::endl;
});
}
在这种情况下,编译器是否可以优化内联函数?也就是说,用
void to_optimize() {
std::cout << "foo" << std::endl;
}
?
答:
3赞
Sam Varshavchik
10/8/2023
#1
C++ 标准允许任何没有可观察效果的优化。如前所述,优化函数调用不会产生可观察到的效果。C++ 程序无法确定此处是否发生了其他函数调用。
所以,是的,C++ 编译器可以优化函数调用。它是否这样做取决于编译器和编译器配置参数。
评论
1赞
Jesper Juhl
10/8/2023
提及“假设规则”或指向 en.cppreference.com/w/cpp/language/as_if 的链接可能会改善您的答案。
1赞
Petr
10/8/2023
#2
@PepijnKramer的评论为我指出了我可以自己探索的地方(有一个稍微简化的例子) - Clang with : https://godbolt.org/z/YEb8vjYev.事实上,编译器完全优化了函数调用。-O2
#include <iostream>
#ifdef AS_FUNCTOR
template <typename F>
void foo(F&& f) {
f(42);
}
void to_optimize() {
foo([](int s) {
std::cout << s;
});
}
#else // AS_FUNCTOR
void to_optimize() {
std::cout << 42;
}
#endif // AS_FUNCTOR
评论
2赞
Peter Cordes
10/8/2023
Compiler-explorer 有一个内置的差异窗格。您可以使用 和 vs. 使相同的源代码编译为排列的不同 ASM。#ifdef
-Dfoo
-Ufoo
2赞
Peter Cordes
10/8/2023
您的 lambda 不使用它的参数,它还使用硬编码的 ,因此编译器在内联后甚至没有任何常量传播。顺便说一句,如果您删除 或至少将其替换为 或 ,asm 会更简单。输出换行符后显式刷新的 asm 只是额外的噪音,并且会使程序运行速度变慢,因此当您不需要刷新流时停止使用,即使它被重定向到文件。42
std::endl
<< '\n'
<< "\n"
std::endl
0赞
Paul Sanders
10/8/2023
@PeterCordes Compiler-explorer 有一个内置的差异窗格 噢噢噢,不错
0赞
Petr
10/9/2023
@PeterCordes 感谢您发现我的错误,确实 lambda 应该使用该参数。让我尝试解决这个问题并重新发布结果。
评论
f("foo");
foo
foo