c++ - GCC/Clang:禁用单个函数的尾递归优化
问题描述
我知道我可以使用选项禁用 GCC 中的尾递归优化-fno-optimize-sibling-calls
。但是,它会禁用整个编译单元的优化。
有没有办法禁用单个功能的优化?
我的理解是我可以更改函数,因此它不是尾递归的有效候选者 - 例如,通过在表达式中使用返回值,因此返回不是函数中的最后一条指令(例如:)return f(n) + 1;
。
不过,上面的解决方案可能仍然是可优化的,并且编译器的未来(或当前,我不知道)版本可能足够聪明,可以使其成为尾调用 - 比如说,通过更改int f(i) { if(!i) return 0; return f(i - 1) + 1; }
为int f(i, r = 0) { if(!i) return r; return f(i - 1, r + 1); }
如果可能的话,我正在寻找一种不需要更改算法的更清洁且面向未来的解决方案。
查看文档,我找不到执行此操作的函数属性或内置函数,但我的搜索并不详尽。
解决方案
您可以使用 GCC 特定的#pragma optimize()
指令(结合适当的括号和 push/pop#pragma
行)来实现类似于指定函数属性的结果:
#pragma GCC push_options // Save current options
#pragma GCC optimize ("no-optimize-sibling-calls")
int test(int i)
{
if (i == 1) return 0;
return i + test(i - 1);
}
#pragma GCC pop_options // Restore saved options
int main()
{
int i = 5;
int j = test(i);
return j;
}
但请注意,clang 不支持这种形式的#pragma optimize
. 另外,请注意手册中的此警告:
并非每个以属性指定的 -f 前缀开头的优化选项都一定会对函数产生影响。optimize 属性应仅用于调试目的。它不适合生产代码。
推荐阅读
- windows - 由于 RDS 许可证问题,RDP Azure VM 无法正常工作
- php - laravel 5.5 通过代理将我的文件存储在 Bucket aws S3 中
- javascript - invisible recaptcha v2 Challenge 在移动端中断
- javascript - 为每条路线随机化谷歌地图折线颜色
- bash - 将标准输入传递给 plistbuddy
- linux - 如何在 Perl 中以 root 身份运行句子
- sql - 更新 cosmosDB 天蓝色 sql
- php - 从 PHP 返回字符串并警告 jQuery 响应
- android - 无法使用照片的 URI 在 Android 的默认图像查看器中打开捕获的照片
- java - OAF 如何将带有搜索字段的高级表格添加到标准现有页面(EBS 12.1)?