C++ 计时器

文章目录

  • 一、简介
  • 二、实现代码
    • 2.1 windows平台
    • 2.2 C++标准库
  • 三、实现效果

一、简介

有时候总是会用到一些计时的操作,这里也整理了一些代码,包括C++标准库以及window自带的时间计算函数。

二、实现代码

2.1 windows平台

StopWatch.h

#ifndef STOP_WATCH_H
#define STOP_WATCH_H

#ifdef _WIN32
#	include <windows.h>
#else 
#	include <sys/time.h>
#endif

/// <summary>
/// 基于Windows平台提供的函数,进行时间计算
/// </summary>

class StopWatch
{
public:
	StopWatch(); // 计时器将自动开始
	~StopWatch();

	void  start();

	// 返回启动以来用户经过的时间(以秒为单位)。
	double elapsed() const;

private:

#ifdef WIN32
	LONGLONG  freq_;
	LONGLONG  start_count_;
#else
	timeval start_time_;
#endif

};

#endif


StopWatch.cpp

#include "StopWatch.h"
#include <iostream>

StopWatch::StopWatch() {
	start();		//开始计时
}

StopWatch::~StopWatch() {}

void StopWatch::start() {
#ifdef WIN32
	LARGE_INTEGER  largeInteger;
	// 获取高精度性能计数器的频率,这个频率通常以每秒的计数数来衡量。
	QueryPerformanceFrequency(&largeInteger);
	freq_ = largeInteger.QuadPart;

	//获取当前性能计数器的值,它表示自系统启动以来的计数次数。
	QueryPerformanceCounter(&largeInteger);
	start_count_ = largeInteger.QuadPart;
#else
	gettimeofday(&start_time_, 0);
#endif
}

template <class T>
inline T clip_precision(T v, int p) {
	float tmp = std::pow(10.0f, p);
	return (static_cast<int>(v * tmp) / tmp);
}

double StopWatch::elapsed() const {
#ifdef WIN32
	LARGE_INTEGER  largeInteger;
	QueryPerformanceCounter(&largeInteger);
	LONGLONG now_count = largeInteger.QuadPart;

	//计算已经经过的时间。
	//计算当前计数值与起始计数值之间的差值,然后将其除以频率来得到时间,以秒为单位。
	double time = (double)((now_count - start_count_) / static_cast<double>(freq_));
	return clip_precision(time, 6);		//保留小数的有效位数
#else
	timeval now;
	gettimeofday(&now, 0);
	double time = (now.tv_sec - start_time_.tv_sec) + (now.tv_usec - start_time_.tv_usec) / 1.0e6;
	return clip_precision(time, 2);
#endif
}

2.2 C++标准库

std::chrono::steady_clock类型

Timer.h

#pragma once

#define NOMINMAX
#undef min
#undef max

#include <chrono>
#include <stdexcept>

/// <summary>
/// 基于C++标准库时间函数,进行计时(支持跨平台使用)
/// </summary>

class Timer
{
public:
    Timer()
        : m_start(std::chrono::steady_clock::time_point::min())
    {
    }

    void clear()
    {
        m_start = std::chrono::steady_clock::time_point::min();
    }

    bool isStarted() const
    {
        return (m_start != std::chrono::steady_clock::time_point::min());       //最小时间点
    }

    void start()
    {
        //steady_clock 是一个专门用于测量时间间隔的时钟,
        //它提供了稳定的、不受系统时间调整影响的时间
        m_start = std::chrono::steady_clock::now();
    }

    std::int64_t getMs() const
    {
        if (!this->isStarted()) {
            throw std::runtime_error("计时器未启动!");
        }

        const std::chrono::steady_clock::duration diff = std::chrono::steady_clock::now() - m_start;
        return std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();
    }

private:
    std::chrono::steady_clock::time_point m_start;
};

std::clock类型

BasicTimer.h

#ifndef TIMER_H
#define TIMER_H

#include <cfloat>

/// <summary>
/// 测量用户进程时间的计时器类, 它只计算处于
/// 运行状态(CPU执行)的时间, 时间信息以秒为单位给出。
/// </summary>

class BasicTimer
{
public:
	BasicTimer() : elapsed_(0.0), started_(0.0), interv_(0), running_(false) {}

	void	start();
	void	stop();
	void	reset();
	bool	is_running() const { return running_; }

	double	time()       const;
	int		intervals()  const { return interv_; }

	double	precision()  const;

private:
	double	user_process_time()     const; //秒
	double	compute_precision() const; //秒

	double	elapsed_;
	double	started_;
	int		interv_;
	bool	running_;

	static bool failed_;
};

#endif

BasicTimer.cpp

#include "BasicTimer.h"

#include <climits>
#include <ctime>
#include <cfloat>
#include <assert.h>
#include <cmath>

bool BasicTimer::failed_ = false;

template <class T>
inline T basic_timer_clip_precision(T v, int p) {
	float tmp = std::pow(10.0f, p);
	return (static_cast<int>(v * tmp) / tmp);
}

double BasicTimer::user_process_time() const {
	// 与操作系统相关。 返回一个单调增加的时间(以秒为单位)
	//(在溢出的情况下可能会回绕,请参阅 max()),
	// 如果该时间的系统调用失败,则返回 0.0。 
	// 如果系统调用失败,则设置静态标志“m_failed”。
	std::clock_t clk = std::clock();
	assert(clk != (std::clock_t)-1);
	if (clk != (std::clock_t)-1) {
		return double(clk) / CLOCKS_PER_SEC;
	}
	else {
		failed_ = true;
		return 0.0;
	}
}

double BasicTimer::compute_precision() const {
	// 动态计算计时器精度(以秒为单位)。
	double min_res = DBL_MAX;
	for (int i = 0; i < 5; ++i) {
		double current = user_process_time();
		if (failed_)
			return -1.0;
		double next = user_process_time();
		while (current >= next) {		// 等到计时器增加
			next = user_process_time();
			if (failed_)
				return -1.0;
		}
		// 获取所有运行的最小时间差。
		if (min_res > next - current)
			min_res = next - current;
	}
	return min_res;
}

double BasicTimer::precision() const {
	// 如果计时器系统调用失败,则第一次调用时计算精度返回 -1.0。
	static double prec = compute_precision();
	return prec;
}

void BasicTimer::start() {
	assert(!running_);
	started_ = user_process_time();
	running_ = true;
	++interv_;
}

void BasicTimer::stop() {
	assert(running_);
	double t = user_process_time();
	elapsed_ += (t - started_);
	started_ = 0.0;
	running_ = false;
}

void BasicTimer::reset() {
	interv_ = 0;
	elapsed_ = 0.0;
	if (running_) {
		started_ = user_process_time();
		++interv_;
	}
	else {
		started_ = 0.0;
	}
}

double BasicTimer::time() const {
	if (running_) {
		double t = user_process_time();
		return basic_timer_clip_precision(elapsed_ + (t - started_), 6);
	}

	return basic_timer_clip_precision(elapsed_, 6);
}

三、实现效果

测试:

#include <iostream>

#include "../StopWatch.h"
#include "../Timer.h"
#include "../BasicTimer.h"

int main()
{
	// ------------------------windows平台----------------------
	StopWatch stopWatch;
	stopWatch.start();

	// --------------------C++标准库(支持跨平台)---------------
	Timer timer;
	timer.start();

	BasicTimer basicTimer;
	basicTimer.start();

	for (int i = 0; i < 10000000; ++i)
	{
		//循环,用于计时
	}

	// ------------------------输出结果----------------------
	std::cout << "StopWatch 计时为:" << stopWatch.elapsed() << "s" << std::endl;
	std::cout << "Timer 计时为:" << timer.getMs() << "ms" << std::endl;
	std::cout << "BasicTimer 计时为:" << basicTimer.time() << "s" << std::endl;

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/634818.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JWT的详解

一.什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应用间安全地传递信息。它是一种紧凑的、自包含的方式&#xff0c;用于在用户和服务之间以 JSON 对象的形式安全地传输信息。 JWT 主要由三部分…

计算机系统基础 7 分支程序的实现

简单条件转移指令 根据单个标志位的值&#xff08;CF&#xff0c; SF&#xff0c;OF&#xff0c;PF&#xff0c;ZF&#xff09;来确定是否转移&#xff0c; 如果条件成立&#xff0c;则&#xff08;EIP&#xff09; 位移量 ➡ EIP&#xff0c;否则什么也不做。 注意&#xff0…

c# 将数据库连接字符串写到配置文件中,及获取

考虑到代码的安全性&#xff0c;已经修改起来的方便性&#xff0c;我们常常不会将数据库连接字符串直接放在代码中&#xff0c;而是将这个字符串放到一个App.config配置文件中&#xff0c;赋值给一个变量&#xff0c;然后再在代码中引用这个变量。 具体做法如下: ①展开项目名称…

微星笔记本618爆款推荐清单,好评有礼活动火热进行中

微星笔记本618爆款推荐清单&#xff0c;好评有礼活动火热进行中 又是一年一度的618大促&#xff0c;作为电子数码产品的主场&#xff0c;准备选购笔记本的消费者早已翘首以盼有更实惠的价格~ 不负期待&#xff0c;微星笔记本携多款性价比爆款笔记本、Claw掌上游戏机&#xff0…

Google Find My Device:科技守护,安心无忧

在数字化的时代&#xff0c;我们的生活与各种智能设备紧密相连。而 Google Find My Device 便是一款为我们提供安心保障的实用工具。 一、Find My Decice Netword的定义 谷歌的Find My Device Netword旨在通过利用Android设备的众包网络的力量&#xff0c;帮助用户安全的定位所…

记录一个更新adobe软件导致加载PDF文件异常的问题

最近由于项目需要,没有办法把原有的adobe正版软件进行了卸载,换了个盗版软件,结果导致我的pdf文件加载的时候出现异常。 报错的语句是这个 string str = System.Environment.CurrentDirectory; // string fileName = MyOpenFileDialog(); axAcroPDF1.LoadFile(…

abs(-2147483648) == 2147483648?

从数学意义上&#xff0c;这是对的。但是&#xff0c;就怕但是。 #include int main() {long long v;v abs(-2147483648);printf("%lld\n", v);return 0; } 输出: -2147483648 我们从source code中一一解开. /* Return the absolute value of I. */ int abs (…

uniapp星空效果

uniapp星空效果 背景实现思路代码实现尾巴 背景 之前在网上看到过一个视频&#xff0c;使用纯css实现过一个星空效果。具体出处找不到了&#xff0c;我们按照他那个思路来实现一个类似的效果&#xff0c;还是先上一张图镇楼&#xff1a; 实现思路 首先我们这个效果使用的是…

Php composer 基础教程

一、什么是Composer&#xff1f; Composer 是 PHP 中的依赖管理工具。它允许声明项目所依赖的库&#xff0c;并且它将为您管理&#xff08;安装/更新&#xff09;它们。 二、如何安装&#xff1f; Linux 系统和 MacOS 系统 直接下载最新稳定版&#xff1a; 然后执行下列命令&…

去中心化的 S3,CESS 首创去中心化对象存储 DeOSS

Web3 在各个领域的应用和发展已成为讨论的焦点&#xff0c;尽管行业对 Web3 的定义各不相同&#xff0c;但一个普遍的共识是 Web3 赋予了用户对其数据的所有权和自主权。这一转变在我们的生活和工作与数字化越来越深入地融合之际至关重要&#xff0c;这意味着所有人类活动很快将…

【Linux】Centos7安装JDK

【Linux】Centos7安装JDK 下载 Oracle 官网下载 JDK17 https://www.oracle.com/cn/java/technologies/downloads/#java17 安装 使用rz命令上传 jdk tar 包&#xff0c;上传失败直接用 xftp 上传 在安装图形界面时&#xff0c;有勾选开发工具&#xff0c;会自动安装 JDK 需要先…

D435相机内参标定(无法直接应用在相机上)

打开roscore和相机 输入 rostopic echo /camera/color/camera_info 从而得到相机的内参 cameraInfo包含D、K、R、P四个矩阵。 矩阵D是失真系数&#xff0c;包括(k1, k2, t1, t2, k3) 矩阵K是相机内参&#xff0c;即 矩阵R是一个3✖3的旋转矩阵&#xff0c;仅对双目相机有效&…

每日5题Day9 - LeetCode 41 - 45

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;41. 缺失的第一个正数 - 力扣&#xff08;LeetCode&#xff09; 今天这道题没有ac&#xff0c;写不动了&#xff0c;下次再通过吧&#xff0c;先给个半成品下次回…

微信小程序画布显示图片绘制矩形选区

wxml <view class"page-body"><!-- 画布 --><view class"page-body-wrapper"><canvas canvas-id"myCanvas" type"2d" id"myCanvas" classmyCanvas bindtouchstart"touchStart" bindtouchmo…

HackTheBox-Machines--Bank

文章目录 0x01 信息收集0x02 文件上传漏洞利用0x03 权限提升方法一&#xff1a;SUID提权方法二&#xff1a;配置不当提权 Bank 测试过程 0x01 信息收集 1.端口扫描 发现 ssh(22)、DNS(53)、HTTP(80) 端口 nmap -sC -sV 10.129.29.200访问 80 端口&#xff0c;页面为Apache2 U…

数据挖掘与机器学习——机器学习概述

一、什么是机器学习 机器学习的英文名称叫Machine Learning&#xff0c;简称ML&#xff0c;该领域主要研究的是如何使计算机能够模拟人类的学习行为从而获得新的知识。 机器学习与数据挖掘的联系&#xff1a;简单来说&#xff0c;机器学习就是让计算机从大量 的数据中学习到相关…

软管的高速非接触外径测量方案!单双轴测径仪多种类型!

一、传统测量方式的局限 在软管外径的测量领域&#xff0c;传统方式往往面临多重挑战&#xff1a; 1、挤压变形&#xff1a;传统的测量方式可能导致软管因挤压而变形&#xff0c;进而影响测量数据的准确性。 2、人为误差&#xff1a;测量结果常因人为因素而有所差异&#xff0c…

Embase生物医学文摘数据库文献全文去哪里查找下载

Embase是生物医学与药理学文摘数据库&#xff0c;是爱思唯尔&#xff08;Elsevier&#xff09;推出的针对生物医学和药理学领域信息所提供的基于网络的数据检索服务。它将1974年以来的生物医学记录与 900 多万条独特的Medline&#xff08;1950 年以来&#xff09;的记录相结合&…

智慧社区管理系统:打造便捷、安全、和谐的新型社区生态

项目背景 在信息化、智能化浪潮席卷全球的今天&#xff0c;人们对于生活品质的需求日益提升&#xff0c;期待居住环境能与科技深度融合&#xff0c;实现高效、舒适、安全的生活体验。在此背景下&#xff0c;智慧社区管理系统应运而生&#xff0c;旨在借助现代信息技术手段&…

go ast语义分析实现指标计算器

什么是AST 首先我们要知道AST是什么&#xff08;Abstract Syntax Tree&#xff0c;AST&#xff09;&#xff0c;简称为语法树&#xff0c;是go语言源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构&#xff0c;树上的每个节点都表示源代码中的一种结构。 …