为什么包含iostream时此代码更快?
Why is this code faster when iostream is included?
>更快的代码:
#include <stdio.h>
#include <iostream>
long fib(int num)
{
if (num <= 1)
return 1;
else
return fib(num-1) + fib(num-2);
}
int main()
{
long res = fib(45);
printf("%lin", res);
return 0;
}
较慢的代码:
#include <stdio.h>
long fib(int num)
{
if (num <= 1)
return 1;
else
return fib(num-1) + fib(num-2);
}
int main()
{
long res = fib(45);
printf("%lin", res);
return 0;
}
两者之间的唯一区别是第二行#include <iostream>
。
两者都使用 clang++ 8.0.0-3 编译,带有 -O2 标志。
clang++-8 -O2 fib.cpp && time ./a.out # 3.59s
clang++-8 -O2 fib_io.cpp && time ./a.out # 3.15s
编辑:
重新启动后行为似乎发生了变化,这次iostream版本更慢,这更有意义。
我倾向于说这只是一种侥幸,因为我无法再重现它了。
当你包括#include <iostream>
时,至少有一个副作用:必须构造和破坏std::ios_base::Init
的实例(参见C++草案[ios.init]p1):
类
Init
描述了一个对象,其构造可确保构造在<iostream>
中声明的八个对象([iostream.objects]),这些对象将文件流缓冲区与<cstdio>
中声明的函数提供的标准 C 流相关联。
来自cpp首选项的解释:
此类用于确保默认的C++流(
std::cin
、std::cout
等)被正确初始化和销毁。该类跟踪创建了多少个实例,并在构造第一个实例时初始化C++流,并在最后一个实例被销毁时刷新输出流。标头
<iostream>
的行为就像它(直接或间接)定义具有静态存储持续时间的std::ios_base::Init
实例一样:这使得通过有序初始化访问静态对象的构造函数和析构函数中的标准 I/O 流变得安全(只要在定义这些对象之前#include <iostream>
包含在转换单元中)
这并不一定意味着性能应该不同(更好或更差)。但是,这意味着从C++标准的角度来看,您的两个程序并不相等。
如果不查看给定标准库中的实际实现(或对其进行分析),我们就无法知道详细原因(随意这样做并添加答案!
检查从 Linux 盒子上的 clang 生成的代码(似乎是您的情况),即libstdc++
:
_GLOBAL__sub_I_a.cpp: # @_GLOBAL__sub_I_a.cpp
push rax
mov edi, offset std::__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edi, offset std::ios_base::Init::~Init() [complete object destructor]
mov esi, offset std::__ioinit
mov edx, offset __dso_handle
pop rax
jmp # TAILCALL
因此,无论是std::ios_base::Init::Init()
还是__cxa_atexit
都会有一些副作用,使整个程序对您来说更快。
- 编译包含字符串的代码时遇到问题
- 在混合代码库中将C转换为C++时出现许多包含错误
- 在C++代码中包含opencv时,使用ctypes创建.so文件
- 如何将外部代码包含在虚幻引擎4 C++项目中
- 如果代码包含多个复杂度循环,如何计算复杂度
- 如何使用 cmake 在代码中包含、构建和调试共享库 (.so)?
- 在 C++ 对象包装器中安全地包含 C 代码
- 为什么我的代码包含错误分段错误(核心转储)?
- 如何在此代码中包含 While 语句
- 在源文件中包含额外的调试信息,以便在代码::块中使用gdb进行调试
- 在Visual Studio代码中包含自定义c++库的问题
- 当我在结构中包含多个数组时,我的程序会跳过一堆代码
- C++:汇编代码包含断言结果
- 如何为代码包含负值?号码系统转换
- C++模板可以用于条件代码包含吗
- 如何将文件作为字符串和代码包含在cpp中
- C++代码包含错误
- c++宏:条件代码包含在表达式NOT语句中
- 端口C代码包含复数到c++
- 将模板代码包含在多个编译单元中,它将始终链接而不内联