自定义Timer类嵌套后在std::thread中失效问题求助
搞定嵌套Timer类在std::thread里失效的问题
嘿,我看你遇到的问题挺典型的:自定义Timer类没嵌套的时候好好的,一放到其他类里面,在std::thread里调用就失效了,start和end时间戳全是同一个值,算出来的耗时永远是0。我来帮你拆解下可能的原因,再给你个能跑的修复方案:
问题大概率出在这几个地方
- 没正确调用
init()方法:如果启动线程前没调用Timer的init(),或者调用时机不对,m_StartTime和m_EndTime都会是默认初始化的同一个值(你看到的1.52426291e+09就是chrono时间戳的初始默认值)。 - 线程拿到的是Timer的副本:创建std::thread的时候如果是值传递Timer对象,线程会生成一个独立的副本,主线程调用的
init()和线程里的update()根本不是在同一个对象上跑的,时间戳当然一样。 - 成员变量类型定义错了:从你给的代码片段看,
m_StartTime和m_EndTime的类型应该用时间点类型(std::chrono::system_clock::time_point),如果直接用time_since_epoch()返回的duration类型,很容易出计算问题。
修复后的完整代码示例
#include <chrono> #include <thread> #include <cstdio> // 外层类,嵌套Timer class OuterClass { public: class Timer { private: // 用时间点类型存储开始/结束时间,这是正确的姿势 std::chrono::system_clock::time_point m_StartTime; std::chrono::system_clock::time_point m_EndTime; public: // 用默认构造/析构就够了 Timer() = default; ~Timer() = default; // 初始化开始时间,必须在要计时的操作前调用 void init() { m_StartTime = std::chrono::system_clock::now(); } // 更新结束时间并计算耗时,返回秒数 double update() { m_EndTime = std::chrono::system_clock::now(); std::chrono::duration<double> elapsed = m_EndTime - m_StartTime; return elapsed.count(); } }; // 在这个方法里启动线程跑Timer void runTimerInThread() { Timer timer; // 先init,再启动线程!顺序不能乱 timer.init(); // 用lambda捕获timer的引用,避免线程创建副本 std::thread timerThread([&timer]() { // 模拟一段耗时操作,比如睡1秒 std::this_thread::sleep_for(std::chrono::seconds(1)); double elapsed = timer.update(); printf("耗时:%.3f 秒\n", elapsed); }); // 别忘了join线程,不然主线程可能先退出 timerThread.join(); } }; int main() { OuterClass outer; outer.runTimerInThread(); return 0; }
关键修复点说清楚
- 修正成员变量类型:把
m_StartTime和m_EndTime改成std::chrono::system_clock::time_point(时间点),而不是直接存time_since_epoch()的结果,这样计算时间差更准确。 - 避免线程拿副本:用lambda的引用捕获(
[&timer]),或者传递指针,确保线程和主线程操作的是同一个Timer对象。 - 调用顺序不能错:一定要在启动线程前调用
init(),这样开始时间是线程执行前的时间点,而不是线程内部初始化的默认值。 - 完善update逻辑:补全时间差的计算,返回你需要的时间单位(这里是秒,要是需要毫秒就换成
std::chrono::duration<double, std::milli>)。
另外,如果你的Timer是OuterClass的成员变量(不是局部变量),要注意线程运行期间OuterClass对象不能被销毁,不然会出现悬空引用的问题哦。
内容的提问来源于stack exchange,提问作者user9589156
相关产品推荐
相关产品推荐

