引子
当时在leetcode刷题时,看到这个问题,大家争论了半天未看到一个合理的答案,就想尝试能不能做实验测试一下三种不同的写法的运行时长
C的方法
一开始想到的是陈越姥姥的《数据结构》中使用的方法,使用time.h
中clock()
但奇怪的是在C++中运行结果全为0.00
偶尔几次结果不为0
Cpp的方法
无奈下,想到了C++
有没有属于自己的测试代码运行时长的库文件
一番寻找,在stackoverflow
找到了解决办法,使用方法如下
#include <chrono>
auto start = std::chrono::steady_clock::now();
// do something
auto finish = std::chrono::steady_clock::now();
double elapsed_seconds = std::chrono::duration_cast<
std::chrono::duration<double> >(finish - start).count();
为了方便测试代码,将那块封装成一个MeasureRuntime()
函数,使用回调函数CallBackFun
作为参数,分别对三种不同写法对应的test()
函数做测试
代码
#include <iostream>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iomanip>
using namespace std;
// 实验数据
int n = 1;
int num[] = {1, 10, 100, 1000, 10000};
unordered_map<int, int> changes;
vector<vector<int> > grid;
// 估计运行时间
double MeasureRuntime(void(*CallBackFun)()) {
auto start = chrono::steady_clock::now();
CallBackFun();
auto finish = chrono::steady_clock::now();
double elapsed_seconds = chrono::duration_cast<
chrono::duration<double> >(finish - start).count();
cout << fixed << setprecision(8) << elapsed_seconds << setw(15);
/* 输出格式:
fixed 不使用科学计数法
setprecision(n) 设置精度,保留n位小数
setw(m) 对齐,从字符左边第一位开始数
*/
}
// 待测试函数
void test1() {
unordered_map<int, int>::iterator it;
for(it = changes.begin(); it != changes.end(); it++ ) {
grid[it->first / n][it->first % n] += it->second;
}
}
void test2() {
for(auto it:changes) {
grid[it.first / n][it.first % n] += it.second;
}
}
void test3() {
for(auto &it:changes) {
grid[it.first / n][it.first % n] += it.second;
}
}
// 重置 changes、grid
void reset() {
grid.resize(n);
for(int j=0; j<n; j++) {
changes[j] = j + 1;
grid[j].resize(n);
}
}
int main() {
cout.setf(ios_base::left);
cout << setw(15) << "num" << setw(15) << "test1:it" << setw(15) <<
"test2:auto" << setw(15) << "test3:auto &" << setw(15) << endl;
for(int i=0; i<5; i++) {
n = num[i];
cout << n << setw(15);
reset();
MeasureRuntime(test1);
MeasureRuntime(test2);
MeasureRuntime(test3);
cout << endl;
}
return 0;
}
结果
/*
num test1:it test2:auto test3:auto &
1 0.00000030 0.00000140 0.00000050
10 0.00000090 0.00000080 0.00000080
100 0.00000600 0.00000420 0.00001770
1000 0.00005470 0.00003350 0.00003490
10000 0.00069710 0.00038380 0.00068700
num test1:it test2:auto test3:auto &
1 0.00000040 0.00000050 0.00000040
10 0.00000080 0.00000080 0.00000080
100 0.00000570 0.00000410 0.00000450
1000 0.00005710 0.00003540 0.00003500
10000 0.00053880 0.00036460 0.00038480
num test1:it test2:auto test3:auto &
1 0.00000030 0.00000060 0.00000060
10 0.00000090 0.00000090 0.00000080
100 0.00000600 0.00000390 0.00000410
1000 0.00005920 0.00003690 0.00005330
10000 0.00055230 0.00035290 0.00032940
100000 terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
*/
/*
the for loop can't sit outside the function
*/
结论
可以发现,处于不同的数量级,三种写法的性能是波动的;
总体来说,
当数量级较大时,性能上:auto &
> auto
> iterator
当数量级较小时,性能上:iterator
> auto &
> auto
Reference
[1]: 陈越姥姥《数据结构》
[2]: Measuring the runtime of a C++ code?
[3]: C++
中setw()
函数
[4]: C++
中的 cout.setf()
函数