林犀艺嚸 發表於 2026-1-7 09:54:06

在C++中测量代码执行时间的两种方法

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>第一部分:C 风格clock()(&ldquo;CPU 秒表&rdquo;)</li><li>第二部分:现代 C++std::chrono(&ldquo;高精度电子秒表&rdquo;)</li><li>第三部分:新手的&ldquo;头号噩梦&rdquo;&mdash;&mdash;clock()vs&lt;chrono&gt;</li><li>第四部分:&ldquo;X光透 视&rdquo;&mdash;&mdash;观察时间点</li><ul class="second_class_ul"><li>&ldquo;X光&rdquo;实战(基于chrono_example.cpp)</li></ul><li>动手试试!(终极挑战:你的&ldquo;排序分析器&rdquo;)</li><ul class="second_class_ul"></ul></ul></div><p>在C++中,编写代码只是第一步,衡量代码的&ldquo;<strong>效率</strong>&rdquo;同样重要。你如何知道你的 <code>sort</code> 算法比同事写的快?或者你的新功能导致了多少性能下降?你需要一个&ldquo;<strong>秒表</strong>&rdquo;来精确测量代码的执行时间。</p>
<p>在C++(及C语言)中,你有两种主要的&ldquo;秒表&rdquo;:</p>
<p><strong>C 风格 &ldquo;CPU 秒表&rdquo; (<code>&lt;ctime&gt;</code>/<code>clock()</code>)</strong>:</p>
<ul><li><strong>比喻:</strong> 这是一个老式的&ldquo;机械秒表&rdquo;,它只在你的 CPU **真正在为你的程序&ldquo;工作&rdquo;(执行指令)**时才会&ldquo;嘀嗒&rdquo;。</li><li><strong>特点:</strong> 它测量的是 <strong>CPU 时间 (CPU Time)</strong>。如果你的程序在&ldquo;<strong>等待</strong>&rdquo;(比如 <code>sleep</code>、等待用户输入或等待网络响应),这个秒表会<strong>暂停</strong>。</li><li><strong>精度:</strong> 较低,受限于 <code>CLOCKS_PER_SEC</code> 宏。</li></ul>
<p><strong>现代 C++ 风格 &ldquo;高精度电子秒表&rdquo; (<code>&lt;chrono&gt;</code>)</strong>:</p>
<ul><li><strong>比喻:</strong> 这是一个高精度的&ldquo;电子秒表&rdquo;,它测量的是<strong>墙上时钟 (Wall Clock)</strong> 走过的时间。</li><li><strong>特点:</strong> 它测量的是<strong>真实世界流逝的时间</strong>。从你按下&ldquo;开始&rdquo;到按下&ldquo;停止&rdquo;,无论你的程序是在&ldquo;工作&rdquo;还是&ldquo;等待&rdquo;,它都在计时。</li><li><strong>精度:</strong> 极高(通常可以达到纳秒 <code>ns</code> 级别)。</li><li><strong>这是现代C++中</strong>(C++11及以后)<strong>强烈推荐</strong>的方式。</li></ul>
<p><strong>在本教程中,你将学会:</strong></p>
<ul><li><strong>C 风格 <code>clock()</code></strong>:如何使用&ldquo;CPU 秒表&rdquo;。</li><li><strong>C++ <code>std::chrono</code></strong>:如何使用&ldquo;高精度电子秒表&rdquo;(<strong>推荐!</strong>)。</li><li><strong>新手的&ldquo;头号噩梦&rdquo;</strong>:<strong>CPU 时间</strong> vs <strong>挂钟时间</strong> (Wall Time) 的致命区别。</li><li><strong>实战演练</strong>:通过代码对比两种计时器的不同结果。</li><li><strong>&ldquo;X光透 视&rdquo;</strong>:用调试器&ldquo;亲眼目睹&rdquo;时间点(<code>time_point</code>)对象。</li></ul>
<p><strong>前置知识说明 (100% 自洽):</strong></p>
<ul><li><strong>变量 (Variable)</strong>:理解存储数据的&ldquo;盒子&rdquo;,如 <code>double time_taken;</code>。</li><li><strong>函数 (Function)</strong>:理解可重复使用的&ldquo;代码积木&rdquo;。</li><li><strong><code>#include</code></strong>:如何包含C++标准库(如 <code>&lt;iostream&gt;</code>, <code>&lt;ctime&gt;</code>, <code>&lt;chrono&gt;</code>)。</li><li><strong><code>cout</code></strong>:C++ 中用于在屏幕上打印信息的&ldquo;扬声器&rdquo;。</li><li><strong>类型转换 (Casting)</strong>:如 <code>double(value)</code>,将 <code>value</code> 转换为 <code>double</code> 类型。</li><li><strong>编译 (Compile)</strong>:C++代码(&ldquo;食谱&rdquo;)必须被&ldquo;编译&rdquo;(&ldquo;烘焙&rdquo;),才能变成电脑可执行的程序(&ldquo;蛋糕&rdquo;)。</li></ul>
<p class="maodian"></p><h2>第一部分:C 风格clock()(&ldquo;CPU 秒表&rdquo;)</h2>
<p><code>clock()</code> 函数在 <code>&lt;ctime&gt;</code> 库中。它返回程序启动到<strong>当前时刻</strong>为止,CPU 花在你程序上的&ldquo;<strong>嘀嗒数</strong>&rdquo;(Clock Ticks)。</p>
<p><strong>核心步骤:</strong></p>
<ol><li>包含 <code>&lt;ctime&gt;</code>。</li><li>在代码开始前,调用 <code>clock_t start = clock();</code> 记录&ldquo;开始嘀嗒数&rdquo;。</li><li>在代码结束后,调用 <code>clock_t end = clock();</code> 记录&ldquo;结束嘀嗒数&rdquo;。</li><li>计算差值 <code>double(end - start)</code>,然后除以 <code>CLOCKS_PER_SEC</code> (一个系统常量,表示&ldquo;每秒多少嘀嗒数&rdquo;),得到<strong>秒数</strong>。</li></ol>
<p><strong><code>clock_example.cpp</code></strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;ctime&gt; // 1. 包含 C 时间库
using namespace std;

// 一个耗时的函数 (模拟 CPU 密集型工作)
void heavy_work() {
    // 执行一个(通常会被编译器优化的)空循环来消耗 CPU 时间
    // 在实际测试时,应使用 -O0 (关闭优化) 来观察
    for(long i = 0; i &lt; 3000000000L; ++i) {}
}

int main() {
    cout &lt;&lt; "--- 测试 C 风格 &lt;ctime&gt; (clock_t) ---" &lt;&lt; endl;
    cout &lt;&lt; "每秒“嘀嗒”数 (CLOCKS_PER_SEC): " &lt;&lt; CLOCKS_PER_SEC &lt;&lt; endl;

    // 1. 获取开始时的“CPU嘀嗒数”
    clock_t start = clock();

    // 2. 执行你的代码
    heavy_work();

    // 3. 获取结束时的“CPU嘀嗒数”
    clock_t end = clock();

    // 4. 计算时间差 (秒)
    double cpu_time_taken = double(end - start) / double(CLOCKS_PER_SEC);

    cout &lt;&lt; "CPU 耗时: " &lt;&lt; cpu_time_taken &lt;&lt; " 秒" &lt;&lt; endl;
   
    return 0;
}
</pre></div>
<p><strong>&ldquo;手把手&rdquo;终端模拟 (结果因机器和编译优化而异):</strong></p>
<div class="jb51code"><pre class="brush:cpp;">PS C:\MyCode&gt; g++ clock_example.cpp -o clock_example.exe -O0 # -O0 关闭优化
PS C:\MyCode&gt; .\clock_example.exe
--- 测试 C 风格 &lt;ctime&gt; (clock_t) ---
每秒“嘀嗒”数 (CLOCKS_PER_SEC): 1000
CPU 耗时: 1.156 秒
</pre></div>
<p><strong>缺点:</strong> 精度不高,且<strong>无法</strong>测量&ldquo;等待&rdquo;时间。</p>
<p class="maodian"></p><h2>第二部分:现代 C++std::chrono(&ldquo;高精度电子秒表&rdquo;)</h2>
<p><code>std::chrono</code> 库 (C++11) 是现代C++的<strong>黄金标准</strong>。它提供了高精度时钟和时间单位(纳秒、微秒、毫秒等)。</p>
<p><strong>核心步骤:</strong></p>
<ol><li>包含 <code>&lt;chrono&gt;</code>。</li><li>使用 <code>auto start = std::chrono::high_resolution_clock::now();</code> 获取<strong>当前挂钟时间点</strong>。</li><li>使用 <code>auto end = std::chrono::high_resolution_clock::now();</code> 获取<strong>结束时间点</strong>。</li><li>计算差值:<code>end - start</code>,得到一个 <code>duration</code> (时间段) 对象。</li><li>使用 <code>std::chrono::duration_cast</code> 将这个 <code>duration</code> 对象转换为你想要的单位(如毫秒)。</li></ol>
<p><strong><code>chrono_example.cpp</code> (推荐用法)</strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;chrono&gt; // 1. 包含 C++11 时间库
#include &lt;thread&gt; // 2. 包含线程库 (用来演示“等待”)
using namespace std;

// 使用 using 来简化类型名 (可选,但推荐)
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::milliseconds;
using std::chrono::microseconds;

// 耗时函数 (包含工作和等待)
void work_and_sleep() {
    // 模拟 CPU 工作
    for(long i = 0; i &lt; 3000000000L; ++i) {}

    // 模拟 I/O 等待或休眠 (500毫秒)
    cout &lt;&lt; "(正在休眠 500 毫秒...)" &lt;&lt; endl;
    std::this_thread::sleep_for(milliseconds(500));
}

int main() {
    cout &lt;&lt; "--- 测试 现代 C++ &lt;chrono&gt; ---" &lt;&lt; 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&lt;milliseconds&gt;(end_time - start_time);
   
    // 5. 打印结果
    cout &lt;&lt; "总耗时 (挂钟时间): " &lt;&lt; duration_total.count() &lt;&lt; " 毫秒" &lt;&lt; endl;

    // 也可以转换为其他单位
    auto duration_us = duration_cast&lt;microseconds&gt;(end_time - start_time);
    cout &lt;&lt; "(即 " &lt;&lt; duration_us.count() &lt;&lt; " 微秒)" &lt;&lt; endl;

    return 0;
}
</pre></div>
<p><strong>&ldquo;手把手&rdquo;终端模拟 (结果因机器而异):</strong></p>
<div class="jb51code"><pre class="brush:cpp;">PS C:\MyCode&gt; g++ chrono_example.cpp -o chrono_example.exe -std=c++11 -O0 -pthread
PS C:\MyCode&gt; .\chrono_example.exe
--- 测试 现代 C++ &lt;chrono&gt; ---
(正在休眠 500 毫秒...)
总耗时 (挂钟时间): 1658 毫秒
(即 1658390 微秒)
</pre></div>
<p><strong>顿悟时刻:</strong> 结果 <code>1658</code> 毫秒,约等于 <code>1158</code> 毫秒 (CPU工作) + <code>500</code> 毫秒 (休眠)。<code>&lt;chrono&gt;</code> <strong>正确地</strong>测量了<strong>所有</strong>流逝的时间!</p>
<p class="maodian"></p><h2>第三部分:新手的&ldquo;头号噩梦&rdquo;&mdash;&mdash;clock()vs&lt;chrono&gt;</h2>
<p>让我们把两个&ldquo;秒表&rdquo;放在<strong>同一个</strong>程序里,测量<strong>同一个</strong>函数,看看它们的区别。</p>
<p><strong><code>comparison.cpp</code> (关键对比)</strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;ctime&gt;
#include &lt;chrono&gt;
#include &lt;thread&gt;
using namespace std;

// (函数 work_and_sleep 同上)
void work_and_sleep() {
    for(long i = 0; i &lt; 3000000000L; ++i) {}
    cout &lt;&lt; "(正在休眠 500 毫秒...)" &lt;&lt; endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

int main() {
    // --- 1. &lt;chrono&gt; 计时 (挂钟时间) ---
    auto start_chrono = std::chrono::high_resolution_clock::now();
   
    // --- 2. &lt;ctime&gt; 计时 (CPU 时间) ---
    clock_t start_clock = clock();

    // --- 3. 执行同一个函数 ---
    cout &lt;&lt; "--- 正在执行 work_and_sleep... ---" &lt;&lt; endl;
    work_and_sleep();
    cout &lt;&lt; "--- 执行完毕 ---" &lt;&lt; endl;

    // --- 4. 获取 &lt;ctime&gt; 结果 ---
    clock_t end_clock = clock();
    double cpu_time = double(end_clock - start_clock) / double(CLOCKS_PER_SEC);
   
    // --- 5. 获取 &lt;chrono&gt; 结果 ---
    auto end_chrono = std::chrono::high_resolution_clock::now();
    auto wall_time_ms = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_chrono - start_chrono);

    // --- 6. 打印对比 ---
    cout &lt;&lt; "\n--- 结果对比 ---" &lt;&lt; endl;
    cout &lt;&lt; "CPU 秒表 (clock()): " &lt;&lt; cpu_time * 1000 &lt;&lt; " 毫秒" &lt;&lt; endl;
    cout &lt;&lt; "电子秒表 (chrono): " &lt;&lt; wall_time_ms.count() &lt;&lt; " 毫秒" &lt;&lt; endl;

    return 0;
}
</pre></div>
<p><strong>&ldquo;手把手&rdquo;终端模拟 (结果因机器而异):</strong></p>
<div class="jb51code"><pre class="brush:cpp;">PS C:\MyCode&gt; g++ comparison.cpp -o comparison.exe -std=c++11 -O0 -pthread
PS C:\MyCode&gt; .\comparison.exe
--- 正在执行 work_and_sleep... ---
(正在休眠 500 毫秒...)
--- 执行完毕 ---

--- 结果对比 ---
CPU 秒表 (clock()): 1162 毫秒 # &lt;-- 只有 CPU 工作的时间!
电子秒表 (chrono): 1663 毫秒 # &lt;-- CPU 工作 (1162) + 休眠 (500)
</pre></div>
<p><strong>&ldquo;黄金法则&rdquo;:</strong></p>
<ul><li>当你想知道&ldquo;<strong>我的代码占用了多少 CPU 资源?</strong>&rdquo;(用于算法分析),<code>clock()</code> 可以用(但 <code>&lt;chrono&gt;</code> 也有 CPU 时钟)。</li><li>当你想知道&ldquo;<strong>用户等了多久?</strong>&rdquo;(从按下按钮到看到结果),<strong>永远</strong>使用 <code>std::chrono::high_resolution_clock</code>!这几乎是你 99% 情况下想要的答案。</li></ul>
<p class="maodian"></p><h2>第四部分:&ldquo;X光透 视&rdquo;&mdash;&mdash;观察时间点</h2>
<p><code>auto start_time = high_resolution_clock::now();</code> 返回的对象是一个 <code>time_point</code>(时间点)。它通常只是一个(非常大的)数字,代表从某个&ldquo;纪 元&rdquo;(比如1970年1月1日,或计算机启动时)到现在的纳秒数。</p>
<p class="maodian"></p><h3>&ldquo;X光&rdquo;实战(基于chrono_example.cpp)</h3>
<ol><li><strong>设置断点:</strong>
<ul><li>在 <code>main</code> 函数的<strong>第31行</strong>(<code>auto start_time = ...</code>)<strong>之后</strong>。</li><li>在 <code>main</code> 函数的<strong>第36行</strong>(<code>auto end_time = ...</code>)<strong>之后</strong>。</li></ul></li><li><strong>启动调试 (F5)。</strong></li><li><strong>第一次&ldquo;冻结&rdquo; (第31行后):</strong><ul><li><strong>观察&ldquo;变量&rdquo;(VARIABLES)窗口:</strong> 找到 <code>start_time</code>。</li><li><strong>展开 <code>start_time</code></strong>:你会看到它内部可能有一个成员,比如 <code>_M_time_since_epoch</code> 或 <code>_Rep</code> (内部表示)。</li><li><strong>你会看到:</strong> 一个<strong>巨大</strong>的数字,例如 <code>1678886400123456789</code> (纳秒)。</li></ul></li><li><strong>继续执行 (F5)。</strong></li><li><strong>第二次&ldquo;冻结&rdquo; (第36行后):</strong><ul><li><strong>观察&ldquo;变量&rdquo;窗口:</strong> 找到 <code>end_time</code>。</li><li><strong>展开 <code>end_time</code></strong>:</li><li><strong>你会看到:</strong> 另一个<strong>巨大</strong>的数字,例如 <code>1678886401783456789</code>。</li></ul></li><li><strong>(关键!)&ldquo;监视&rdquo; (WATCH) 窗口:</strong><ul><li><strong>动作:</strong> 在&ldquo;监视&rdquo;窗口中,添加<strong>这个</strong>表达式:<br /><code>std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_time - start_time).count()</code></li><li><strong>你会看到:</strong> <code>1660</code> (或者你的实际测量值)!</li><li><strong>顿悟时刻:</strong> 调试器向你展示了 <code>chrono</code> 库是如何通过两个&ldquo;时间点&rdquo;相减,得到一个&ldquo;时间段&rdquo;,并最终转换为你需要的单位的。</li></ul></li></ol>
<p class="maodian"></p><h2>动手试试!(终极挑战:你的&ldquo;排序分析器&rdquo;)</h2>
<p>现在,你来当一次&ldquo;算法分析师&rdquo;。</p>
<p><strong>任务:</strong></p>
<ol><li>&ldquo;激活&rdquo; <code>iostream</code>, <code>vector</code>, <code>algorithm</code> (为了 <code>std::sort</code>), <code>chrono</code> 和 <code>random</code> (为了生成随机数)。</li><li>创建一个<strong>非常大</strong>的 <code>vector&lt;int&gt;</code> (例如,<code>1,000,000</code> 个元素),并用<strong>随机</strong>数字填充它。</li><li>使用 <strong><code>std::chrono</code></strong>(高精度电子秒表):<ul><li>在调用 <code>std::sort</code> <strong>之前</strong>,获取&ldquo;开始时间&rdquo;。</li><li>调用 <code>std::sort(myVector.begin(), myVector.end());</code>。</li><li>在 <code>std::sort</code> <strong>之后</strong>,获取&ldquo;结束时间&rdquo;。</li></ul></li><li>计算时间差,并<strong>以毫秒 (milliseconds)</strong> 为单位,<strong>打印</strong>出排序一百万个随机整数所花费的时间。</li></ol>
<p><strong><code>sort_timer.cpp</code> (你的 TODO):</strong></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt; // 需要 std::sort
#include &lt;chrono&gt;    // 需要计时
#include &lt;random&gt;    // 需要随机数
using namespace std;

// (使用 using std::chrono::... 来简化)
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;

int main() {
    // --- 1 &amp; 2: 创建并填充 100 万个随机数 ---
    const int N = 1000000;
    vector&lt;int&gt; numbers;
    numbers.reserve(N); // 预分配内存,提高效率
   
    std::random_device rd;// 随机数种子源
    std::mt19937 gen(rd()); // 随机数引擎
    std::uniform_int_distribution&lt;&gt; distrib(1, N); // 分布范围
   
    cout &lt;&lt; "正在生成 " &lt;&lt; N &lt;&lt; " 个随机数..." &lt;&lt; endl;
    for (int i = 0; i &lt; N; ++i) {
      numbers.push_back(distrib(gen));
    }
    cout &lt;&lt; "生成完毕。" &lt;&lt; endl;

    // --- TODO 3: 计时 ---
    cout &lt;&lt; "\n--- 开始排序... ---" &lt;&lt; endl;
   
    // auto startTime = ...;
   
    // std::sort(... , ...); // 执行排序
   
    // auto endTime = ...;
   
    // --- TODO 4: 计算并打印 ---
    // auto timeTaken_ms = ...;
   
    // cout &lt;&lt; "排序 " &lt;&lt; N &lt;&lt; " 个元素耗时: "
    //      &lt;&lt; timeTaken_ms.count() &lt;&lt; " 毫秒" &lt;&lt; endl;

    return 0;
}
</pre></div>
<blockquote><p>这个挑战让你实践了如何使用 std::chrono 来测量一个<strong>真实</strong>、<strong>有意义</strong>的计算任务(std::sort)的性能。完成它,你就掌握了C++中最重要、最准确的计时工具!</p></blockquote>
<p>以上就是在C++中测量代码执行时间的两种方法的详细内容,更多关于C++测量代码执行时间的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>C++实时控制系统代码执行时间优化深度指南</li><li>c++&nbsp;chrono&nbsp;获取当前时间的实现代码</li><li>C++实现统计代码运行时间的示例详解</li><li>C/C++实现获取系统时间的示例代码</li><li>C++实现统计代码运行时间计时器的简单实例</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 在C++中测量代码执行时间的两种方法