You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否实现以函数为参数的重复执行计时函数?

你的计时函数需求完全可行!

当然没问题!这种封装重复计时逻辑的需求在C++里非常常见,刚好能帮你把重复的代码抽出来,让各个作业环节的计时代码更简洁。下面给你详细的实现思路和代码示例:

核心实现思路

1. 支持两种调用方式

用函数重载或者默认参数就能实现timingRoutine(functionName)和timingRoutine(repetitions, functionName)两种调用形式。推荐用重载,配合模板来兼容不同参数的目标函数。

2. 兼容带参数的目标函数

你的countLastName有三个参数,直接传函数指针没法带参数,所以需要用模板+完美转发来处理任意参数的函数,或者用std::bind绑定参数后再传入。

3. 复用你已有的计时逻辑

你原来用clock()统计CPU时间的思路是对的,它比墙钟时间(比如std::chrono::system_clock)更适合计算函数执行的实际耗时,因为它只统计程序占用的CPU资源,不受其他进程影响。

完整代码示例

#include <iostream>
#include <ctime>
#include <functional>
#include <string>

// 假设你的Person结构体定义
struct Person {
    std::string firstName;
    std::string lastName;
};

// 模板版本:支持指定重复次数,兼容任意参数的可调用对象
template<typename Func, typename... Args>
double timingRoutine(int repetitions, Func func, Args&&... args) {
    // 可选:先调用一次排除缓存预热的影响
    std::invoke(func, std::forward<Args>(args)...);
    
    clock_t startTime = clock();
    for(int i = 0; i < repetitions; ++i) {
        std::invoke(func, std::forward<Args>(args)...);
    }
    clock_t endTime = clock();
    
    // 计算单次平均耗时
    return static_cast<double>(endTime - startTime) / CLOCKS_PER_SEC / repetitions;
}

// 重载版本:使用默认重复次数(和你原来的100000一致)
template<typename Func, typename... Args>
double timingRoutine(Func func, Args&&... args) {
    const int DEFAULT_REPS = 100000;
    return timingRoutine(DEFAULT_REPS, func, std::forward<Args>(args)...);
}

// 你的countLastName函数
int countLastName(const std::string& lastName, const Person* peopleArray, size_t size) {
    int count = 0;
    for(size_t i = 0; i < size; ++i) {
        if(peopleArray[i].lastName == lastName) {
            ++count;
        }
    }
    return count;
}

// 使用示例
int main() {
    Person people[] = {{"Alice", "Smith"}, {"Bob", "Smith"}, {"Charlie", "Brown"}};
    size_t arrSize = sizeof(people) / sizeof(people[0]);

    // 调用方式1:用默认重复次数
    double avgTime1 = timingRoutine(countLastName, "Smith", people, arrSize);
    std::cout << "默认10万次重复,单次平均耗时:" << avgTime1 * 1e6 << " 微秒\n";

    // 调用方式2:指定重复次数
    double avgTime2 = timingRoutine(500000, countLastName, "Smith", people, arrSize);
    std::cout << "50万次重复,单次平均耗时:" << avgTime2 * 1e6 << " 微秒\n";

    return 0;
}

关键细节说明

  • std::invoke:兼容普通函数、lambda表达式、成员函数等各种可调用对象,比直接调用更灵活。
  • 完美转发std::forward<Args>(args)...:保证参数传递时的效率,避免不必要的拷贝(比如你的std::string参数)。
  • 缓存预热:代码里注释的那行提前调用函数,是为了避免第一次执行时的缓存加载开销影响计时结果,如果你不需要可以删掉。

额外优化建议

  • 自动调整重复次数:如果你的函数执行极快,固定重复次数可能导致计时误差大。可以改成循环直到总耗时超过0.1秒,再计算平均耗时,这样结果更准确。
  • 输出格式化:把耗时转换成微秒(乘以1e6)或者纳秒,比直接输出秒数更直观,因为单次函数耗时通常很小。
  • 封装成类(可选):如果作业里需要更复杂的计时(比如多次测试取中位数),可以把计时逻辑封装成一个类,方便扩展。

内容的提问来源于stack exchange,提问作者JohnBoyTheGreat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:35:41