在C++中测量代码执行时间的两种方法
2026/5/25 13:04:06 网站建设 项目流程

在C++中,编写代码只是第一步,衡量代码的“效率”同样重要。你如何知道你的sort算法比同事写的快?或者你的新功能导致了多少性能下降?你需要一个“秒表”来精确测量代码的执行时间。

在C++(及C语言)中,你有两种主要的“秒表”:

C 风格 “CPU 秒表” (<ctime>/clock())

  • 比喻:这是一个老式的“机械秒表”,它只在你的 CPU **真正在为你的程序“工作”(执行指令)**时才会“嘀嗒”。
  • 特点:它测量的是CPU 时间 (CPU Time)。如果你的程序在“等待”(比如sleep、等待用户输入或等待网络响应),这个秒表会暂停
  • 精度:较低,受限于CLOCKS_PER_SEC宏。

现代 C++ 风格 “高精度电子秒表” (<chrono>)

  • 比喻:这是一个高精度的“电子秒表”,它测量的是墙上时钟 (Wall Clock)走过的时间。
  • 特点:它测量的是真实世界流逝的时间。从你按下“开始”到按下“停止”,无论你的程序是在“工作”还是“等待”,它都在计时。
  • 精度:极高(通常可以达到纳秒ns级别)。
  • 这是现代C++中(C++11及以后)强烈推荐的方式。

在本教程中,你将学会:

  • C 风格clock():如何使用“CPU 秒表”。
  • C++std::chrono:如何使用“高精度电子秒表”(推荐!)。
  • 新手的“头号噩梦”CPU 时间vs挂钟时间(Wall Time) 的致命区别。
  • 实战演练:通过代码对比两种计时器的不同结果。
  • “X光透 视”:用调试器“亲眼目睹”时间点(time_point)对象。

前置知识说明 (100% 自洽):

  • 变量 (Variable):理解存储数据的“盒子”,如double time_taken;
  • 函数 (Function):理解可重复使用的“代码积木”。
  • #include:如何包含C++标准库(如<iostream>,<ctime>,<chrono>)。
  • cout:C++ 中用于在屏幕上打印信息的“扬声器”。
  • 类型转换 (Casting):如double(value),将value转换为double类型。
  • 编译 (Compile):C++代码(“食谱”)必须被“编译”(“烘焙”),才能变成电脑可执行的程序(“蛋糕”)。

第一部分:C 风格clock()(“CPU 秒表”)

clock()函数在<ctime>库中。它返回程序启动到当前时刻为止,CPU 花在你程序上的“嘀嗒数”(Clock Ticks)。

核心步骤:

  1. 包含<ctime>
  2. 在代码开始前,调用clock_t start = clock();记录“开始嘀嗒数”。
  3. 在代码结束后,调用clock_t end = clock();记录“结束嘀嗒数”。
  4. 计算差值double(end - start),然后除以CLOCKS_PER_SEC(一个系统常量,表示“每秒多少嘀嗒数”),得到秒数

clock_example.cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include <iostream>

#include <ctime> // 1. 包含 C 时间库

usingnamespacestd;

// 一个耗时的函数 (模拟 CPU 密集型工作)

voidheavy_work() {

// 执行一个(通常会被编译器优化的)空循环来消耗 CPU 时间

// 在实际测试时,应使用 -O0 (关闭优化) 来观察

for(longi = 0; i < 3000000000L; ++i) {}

}

intmain() {

cout <<"--- 测试 C 风格 <ctime> (clock_t) ---"<< endl;

cout <<"每秒“嘀嗒”数 (CLOCKS_PER_SEC): "<< CLOCKS_PER_SEC << endl;

// 1. 获取开始时的“CPU嘀嗒数”

clock_tstart =clock();

// 2. 执行你的代码

heavy_work();

// 3. 获取结束时的“CPU嘀嗒数”

clock_tend =clock();

// 4. 计算时间差 (秒)

doublecpu_time_taken =double(end - start) /double(CLOCKS_PER_SEC);

cout <<"CPU 耗时: "<< cpu_time_taken <<" 秒"<< endl;

return0;

}

“手把手”终端模拟 (结果因机器和编译优化而异):

1

2

3

4

5

PS C:\MyCode> g++ clock_example.cpp -o clock_example.exe -O0 # -O0 关闭优化

PS C:\MyCode> .\clock_example.exe

--- 测试 C 风格 <ctime> (clock_t) ---

每秒“嘀嗒”数 (CLOCKS_PER_SEC): 1000

CPU 耗时: 1.156 秒

缺点:精度不高,且无法测量“等待”时间。

第二部分:现代 C++std::chrono(“高精度电子秒表”)

std::chrono库 (C++11) 是现代C++的黄金标准。它提供了高精度时钟和时间单位(纳秒、微秒、毫秒等)。

核心步骤:

  1. 包含<chrono>
  2. 使用auto start = std::chrono::high_resolution_clock::now();获取当前挂钟时间点
  3. 使用auto end = std::chrono::high_resolution_clock::now();获取结束时间点
  4. 计算差值:end - start,得到一个duration(时间段) 对象。
  5. 使用std::chrono::duration_cast将这个duration对象转换为你想要的单位(如毫秒)。

chrono_example.cpp(推荐用法)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

#include <iostream>

#include <chrono> // 1. 包含 C++11 时间库

#include <thread> // 2. 包含线程库 (用来演示“等待”)

usingnamespacestd;

// 使用 using 来简化类型名 (可选,但推荐)

usingstd::chrono::high_resolution_clock;

usingstd::chrono::duration_cast;

usingstd::chrono::duration;

usingstd::chrono::milliseconds;

usingstd::chrono::microseconds;

// 耗时函数 (包含工作和等待)

voidwork_and_sleep() {

// 模拟 CPU 工作

for(longi = 0; i < 3000000000L; ++i) {}

// 模拟 I/O 等待或休眠 (500毫秒)

cout <<" (正在休眠 500 毫秒...)"<< endl;

std::this_thread::sleep_for(milliseconds(500));

}

intmain() {

cout <<"--- 测试 现代 C++ <chrono> ---"<< endl;

// 1. 获取开始时间点

auto start_time = high_resolution_clock::now();

// 2. 执行你的代码

work_and_sleep();

// 3. 获取结束时间点

auto end_time = high_resolution_clock::now();

// 4. 计算时间差

// 结果是一个 duration 对象

auto duration_total = duration_cast<milliseconds>(end_time - start_time);

// 5. 打印结果

cout <<"总耗时 (挂钟时间): "<< duration_total.count() <<" 毫秒"<< endl;

// 也可以转换为其他单位

auto duration_us = duration_cast<microseconds>(end_time - start_time);

cout <<" (即 "<< duration_us.count() <<" 微秒)"<< endl;

return0;

}

“手把手”终端模拟 (结果因机器而异):

1

2

3

4

5

6

PS C:\MyCode> g++ chrono_example.cpp -o chrono_example.exe -std=c++11 -O0 -pthread

PS C:\MyCode> .\chrono_example.exe

--- 测试 现代 C++ <chrono> ---

(正在休眠 500 毫秒...)

总耗时 (挂钟时间): 1658 毫秒

(即 1658390 微秒)

顿悟时刻:结果1658毫秒,约等于1158毫秒 (CPU工作) +500毫秒 (休眠)。<chrono>正确地测量了所有流逝的时间!

第三部分:新手的“头号噩梦”——clock()vs<chrono>

让我们把两个“秒表”放在同一个程序里,测量同一个函数,看看它们的区别。

comparison.cpp(关键对比)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

#include <iostream>

#include <ctime>

#include <chrono>

#include <thread>

usingnamespacestd;

// (函数 work_and_sleep 同上)

voidwork_and_sleep() {

for(longi = 0; i < 3000000000L; ++i) {}

cout <<" (正在休眠 500 毫秒...)"<< endl;

std::this_thread::sleep_for(std::chrono::milliseconds(500));

}

intmain() {

// --- 1. <chrono> 计时 (挂钟时间) ---

auto start_chrono = std::chrono::high_resolution_clock::now();

// --- 2. <ctime> 计时 (CPU 时间) ---

clock_tstart_clock =clock();

// --- 3. 执行同一个函数 ---

cout <<"--- 正在执行 work_and_sleep... ---"<< endl;

work_and_sleep();

cout <<"--- 执行完毕 ---"<< endl;

// --- 4. 获取 <ctime> 结果 ---

clock_tend_clock =clock();

doublecpu_time =double(end_clock - start_clock) /double(CLOCKS_PER_SEC);

// --- 5. 获取 <chrono> 结果 ---

auto end_chrono = std::chrono::high_resolution_clock::now();

auto wall_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end_chrono - start_chrono);

// --- 6. 打印对比 ---

cout <<"\n--- 结果对比 ---"<< endl;

cout <<"CPU 秒表 (clock()): "<< cpu_time * 1000 <<" 毫秒"<< endl;

cout <<"电子秒表 (chrono): "<< wall_time_ms.count() <<" 毫秒"<< endl;

return0;

}

“手把手”终端模拟 (结果因机器而异):

1

2

3

4

5

6

7

8

9

PS C:\MyCode> g++ comparison.cpp -o comparison.exe -std=c++11 -O0 -pthread

PS C:\MyCode> .\comparison.exe

--- 正在执行 work_and_sleep... ---

(正在休眠 500 毫秒...)

--- 执行完毕 ---

--- 结果对比 ---

CPU 秒表 (clock()): 1162 毫秒 # <-- 只有 CPU 工作的时间!

电子秒表 (chrono): 1663 毫秒 # <-- CPU 工作 (1162) + 休眠 (500)

“黄金法则”:

  • 当你想知道“我的代码占用了多少 CPU 资源?”(用于算法分析),clock()可以用(但<chrono>也有 CPU 时钟)。
  • 当你想知道“用户等了多久?”(从按下按钮到看到结果),永远使用std::chrono::high_resolution_clock!这几乎是你 99% 情况下想要的答案。

第四部分:“X光透 视”——观察时间点

auto start_time = high_resolution_clock::now();返回的对象是一个time_point(时间点)。它通常只是一个(非常大的)数字,代表从某个“纪 元”(比如1970年1月1日,或计算机启动时)到现在的纳秒数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询