编辑:我已经更改了源代码以使用额外的结构而不是那么好的元组。
编辑:这个问题已经解决了,虽然我没有找到原因,但我重建了代码,以便它不依赖于嵌套而是依赖额外的变量检查新发现,问题在底部!
我已经设置了SFML项目。我有一个简单的类,用于处理周期性事件。
类别:
#ifndef _TIMER_H_
#define _TIMER_H_
#include <SFML/System.hpp>
#include <vector>
#include <functional>
#include <tuple>
namespace lg{
struct TimerData{
bool periodic;
std::function<void()> function;
sf::Clock clock;
float timeout;
float runTime;
bool toRemove;
bool stopEss;
};
class Timer{
std::vector<TimerData> vec;
public:
Timer() : vec() {}
Timer(const Timer& t) : vec(t.vec) {}
Timer(Timer&& t) : vec(std::move(t.vec)) {}
Timer& operator=(const Timer& t)
{
vec = t.vec;
return *this;
}
Timer& operator=(Timer&& t)
{
vec = std::move(t.vec);
return *this;
}
void onTimeout(float timeMilliseconds, std::function<void()> callback)
{
TimerData dat;
dat.periodic = false;
dat.timeout = timeMilliseconds;
dat.function = callback;
dat.toRemove = false;
dat.runTime = 0;
dat.clock = sf::Clock();
dat.stopEss = false;
vec.push_back(dat);
}
void onPeriod(float timeMilliseconds, std::function<void()> callback)
{
TimerData dat;
dat.periodic = true;
dat.timeout = timeMilliseconds;
dat.function = callback;
dat.toRemove = false;
dat.runTime = 0;
dat.clock = sf::Clock();
dat.stopEss = false;
vec.push_back(dat);
}
void onPeriod(float timeMilliseconds, float initialDelay, std::function<void()> callback)
{
onTimeout(initialDelay, [=](){ onPeriod(timeMilliseconds, callback); });
}
void onTempPeriod(float timeMilliseconds, float runFor, std::function<void()> callback)
{
TimerData dat;
dat.periodic = true;
dat.timeout = timeMilliseconds;
dat.function = callback;
dat.toRemove = false;
dat.runTime = runFor;
dat.clock = sf::Clock();
dat.stopEss = true;
vec.push_back(dat);
}
void onTempPeriod(float timeMilliseconds, float initialDelay, float runFor,
std::function<void()> callback)
{
onTimeout(initialDelay, [=](){
onTempPeriod(timeMilliseconds, runFor, callback);
});
}
void check()
{
bool removeOne = false;
for(int i = 0; i < vec.size(); ++i)
{
auto& a = vec.at(i);
auto elapsed = a.clock.getElapsedTime().asMilliseconds();
if (elapsed >= a.timeout)
{
a.function();
if (a.periodic)
{
a.clock.restart();
a.runTime -= elapsed;
if (a.stopEss && a.runTime <= 0.f)
{
removeOne = true;
a.toRemove = true;
}
}
else
{
a.toRemove = true;
removeOne = true;
}
}
}
if (removeOne)
{
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const TimerData& t){
return t.toRemove;
}),
vec.end());
}
}
};
}
#endif //_TIMER_H_
如果您尝试运行:
std::cout << "testing timer:\n";
lg::Timer t;
t.onTempPeriod(500.f, 5000.f, [](){std::cout << "timeout\n"; });
while(1)
{
t.check();
}
它工作正常,定时器每500毫秒打印一次“超时\ n”,持续5秒,之后没有任何反应。
但是如果你试图运行onTempPeriod的第二次重载:
t.onTempPeriod(500.f, 1000.f, 3000.f, [](){std::cout << "timeout\n"; });
(第一个参数是每次调用lambda的频率 第二个参数是在调用它之前应该等待多长时间 第三个论点是它应该工作多久)
在1秒初始等待时间后,程序弹出“Program.exe已触发制动点”。错误甚至没有命名,而刹车点在这里:retval = HeapFree(_crtheap, 0, pBlock);
是free.c文件的第50行。
我跳过代码,执行vec.erase(..., vec.end());
时调用错误。在这种特殊情况下,必须对整个矢量进行检测,并在Visual的实现中进行检查。因此它在向量上调用clear()
,它调用一些函数,当程序进入Allocator::destroy
时,它看起来像:
template<class _Uty>
void destroy(_Uty *_Ptr)
{ // destroy object at _Ptr
_Ptr->~_Uty();
}
当执行到达_Ptr-&gt; ~_Uty()时,它只是触发刹车点。
对此有何帮助?
要注意,这对所有其他函数完全正常,并且很可能不是因为onTempPeriod
中的嵌套插入。通过调用onPeriod
的工作onTimeout
证明了这一点。
编辑部分:这真的是组合的事情。无论是在函数内部还是在main函数内部,此代码都将始终触发错误。
t.onTimeout(1000.f, [&](){
t.onTempPeriod(500.f, 1000.f, [](){std::cout << "a\n";});
});