C++中没有睡眠和只有局部变量的计时器[关闭]

ttygqcqt  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(148)

已关闭,此问题需要更focused。目前不接受答复。
**想改善这个问题吗?**更新问题,使其仅通过editing this post关注一个问题。

4天前关闭。
Improve this question

#include <iostream>
#include <chrono>
#include <thread>

bool isSignalExpired(const bool &aExpectedSignal,
                     const bool &aInputSignal,
                     const int &aTimeToExpireInMilliseconds) {
  std::chrono::steady_clock::time_point lStartTime;
  if (aInputSignal != aExpectedSignal) {
    lStartTime = std::chrono::steady_clock::now();
    return false;
  } else {
    return std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now() - lStartTime
    ).count() >= aTimeToExpireInMilliseconds ? true : false;
  }
}

int main()
{
    const int aTimeToExpireInMilliseconds = 5 * 1000;
    bool lSignal = false;
    while (1)
    {
        if(isSignalExpired(false, lSignal , aTimeToExpireInMilliseconds))
        {
            std::cout << "breaking" << std::endl;   
            break;
        }
    }
   return 0;
}

我有些困惑。

  1. std::chrono::steady_clock::time_point lStartTime;是局部变量。它是在每次while循环开始时定义。为什么循环在5秒后中断?
    我用this online compiler.
    1.我不能在isSignalExpired之外声明任何变量。
    1.我不能在循环中使用循环。
    1.我不能使用睡眠。
    如果你能用简单的术语解释这个场景就太好了。先谢谢你了。
7lrncoxx

7lrncoxx1#

新问题解答

在“更新”(即与原始问题完全不同)的问题中,我们现在有一个函数被重复调用:

while (1)
    {
        if(isSignalExpired(false, lSignal , aTimeToExpireInMilliseconds))
        {
            std::cout << "breaking" << std::endl;   
            break;
        }
    }

...(显然)我们的工作是实现isSignalExpired,而不改变该函数之外的任何代码。
在本例中,您希望在函数中有一个static变量,以便在第一次调用函数时初始化它,并在后续调用中保留其值。

bool isSignalExpired(int durationMs) {
    using namespace std::chrono;

    static auto start = steady_clock::now();

    auto now = steady_clock::now();
    return duration_cast<milliseconds>(now - start).count() > durationMs;
}

这应该像演示程序一样工作,它只在一个地方使用这个函数(当然,要按原样使用该代码,它还需要接受几个bool参数,它会忽略这些参数)。
但在真实的使用中,这有一个问题:一旦开始时间被初始化,它就不再被更新。因此,如果我们在第二个位置使用它,它将从第一次调用时开始测量时间,而不是从第二个循环的开始。为了解决这个问题,我们可以添加一个布尔参数来告诉它设置它的开始时间:

bool isSignalExpired(bool init, int durationMs) {
    using namespace std::chrono;

    static steady_clock::time_point start;

    if (init) {
        start = steady_clock::now();
        return false;
    }

    auto now = steady_clock::now();
    return duration_cast<milliseconds>(now-start).count() > durationMs;
}

然后要使用它,你需要按照这个一般顺序编写代码:

isSignalExpired(true, 0);
while (!isSignalExpired(false, realDuration)
    ;

但是,至于使它正确地工作与调用所示的问题(因为它站在这一刻),对不起,但没有。根本做不到。问题中的其余代码传递了两个布尔参数(几乎没有解释它们应该是什么意思),但总是为它们传递false,所以不可能以任何有意义的方式使用任何一个。特别是,我们需要函数做两件完全不同的事情:

  • 设置开始时间
  • 从当前设置的开始时间开始测量时间

...我们需要传递一些参数,告诉它在任何特定的调用中要做哪一个。
顺便说一句:这是一个“可怕的”设计。一个函数应该执行一个功能,而不是两个。考虑到我们谈论的是C++,纠正这种情况的明显方法是创建一个小类而不是单个函数:

class signal {
    std::chrono::steady_clock::time_point start;
    std::chrono::steady_clock::time_point end;
public:
    signal(int ms) : 
        start(std::chrono::steady_clock::now()),
        end(start + std::chrono::milliseconds(ms) 
    { }

    bool expired() const { 
        return std::chrono::steady_clock::now() >= end;
    }
};

我们会使用这个类似于:

signal foo{5000};

while (!foo.expired())
    ;

我们不再需要显式指定特定调用是设置开始时间还是从当前开始时间开始测量,因为我们在ctor中设置了开始时间,并在expired()中从当前开始时间开始测量。

原问题解答

bool isInitialized = false;
while (1)
{
    std::chrono::steady_clock::time_point lStartTime;

这将默认初始化lStartTime。在chrono::time_point的情况下,默认初始化意味着它被初始化为时钟的历元。对于一个典型的类UNIX时钟,这将是午夜,1970年1月1日。

if(!isInitialized) {
        lStartTime = std::chrono::steady_clock::now();
        isInitialized = true;
    }

然后在循环的第一次(也只有第一次)迭代中,lStartTime被分配了当前时间。
因此,在循环的第二次迭代中,lStartTime不会被分配当前时间--这意味着您将测量自1970年1月1日以来的毫秒数,发现这超过5秒,然后退出循环。
你可能想要的是更像这样的东西:

using namespace std::chrono;
using std::literals;

auto startTime = steady_clock::now();
while (1) {
    auto currentTime = steady_clock::now();
    if (currentTime - startTime > 5s)
        break;
}

当然,你也可以做一件理智的事:

std::this_thread::sleep_for(5s);
zmeyuzjn

zmeyuzjn2#

您在while循环中声明了lStartTime,但在一次迭代之后,lStartTime被重新声明。此时isInitialized被设置为true,因此lStartTime被默认初始化为epoch的开始。纪元的开始(1970年1月1日)不在当前时间的5秒内(至少在本文发布时),因此循环立即中断。
要解决这个问题,请在循环外部声明lStartTime

bool isInitialized = false;
std::chrono::steady_clock::time_point lStartTime;
while (1)
{
     //...

相关问题