保存计时器集合的最佳方法(对象与指针)

Posted

技术标签:

【中文标题】保存计时器集合的最佳方法(对象与指针)【英文标题】:Best way to keep a collection of timers (object vs pointer) 【发布时间】:2018-08-23 04:04:45 【问题描述】:

我一直在尝试为chrono 的high_performance_clock 实现一个包装类。基本上有一个诊断母类,它保存一个TaskTimers 的容器。到目前为止,我一直将它们作为原始指针保留在 std::vector<TaskTimer*> 列表中,但是阅读了智能指针和指针与对象的讨论,我不知道该怎么想。根据实验,结果似乎可以支持或反对。

对于在这种情况下什么被认为是“正确的”,是否存在普遍共识? 我正在寻找性能而不是可读性。

Diagnostics 类允许程序员将计时器放置在代码的任何位置,以及启动、暂停和停止它们。可以通过name(std::string)id(int) 访问它们。

std::unique_ptr<std::vector<std::shared_ptr<TaskTimer>>> m_TimerList;

来自诊断的片段:

inline int AddTimer(const std::string& timerName, bool runImmediately = true) 
        if (IsEnabled()) 
            auto it = std::find_if(m_TimerList->begin(), m_TimerList->end(), [timerName](TaskTimer* obj)  return obj->GetName() == timerName; );
            if (it != m_TimerList->end())  return -1;  // exists
            else 
                std::shared_ptr<TaskTimer> t(new TaskTimer(timerName, m_NextID, m_Debug));
                m_TimerList->push_back(t);
                if (runImmediately)  _Start(t); 
                return m_NextID++;
            
            return -1;
        
        return -2;
    

inline void Start(const int timerID) 
    auto el = _GetFromID(timerID);
    if (el != nullptr)  _Start(el); 


inline void Pause(const std::string& timerName) 
    if (!IsEnabled())  return; 
    auto el = _GetFromName(timerName);
    if (el != nullptr)  el->Pause(); 


inline std::shared_ptr<TaskTimer> _GetFromID(const int id) const 
    const auto it = std::find_if(m_TimerList->begin(), m_TimerList->end(), [&id](std::shared_ptr<TaskTimer>& obj) return obj->GetID() == id; );
    if (it != m_TimerList->end())  return (*it); 
    return nullptr;


inline std::shared_ptr<TaskTimer> _GetFromName(const std::string& name) const 
    const auto it = std::find_if(m_TimerList->begin(), m_TimerList->end(), [&name](std::shared_ptr<TaskTimer>& obj) return obj->GetName() == name; );
    if (it != m_TimerList->end())  return (*it); 
    return nullptr;


inline void _Start(std::shared_ptr<TaskTimer> t) 
    if (!t->IsStarted()) 
        t->Start();
        m_StartedCount++;
    
    else 
        if (!t->IsRunning())  t->Start(); 
        else                  t->Resume(); 
    

我想了解这里关于对象/指针管理的“正确”选择背后的原因。我收集的TaskTimers 是否像现在这样最适合性能?在保留当前功能的同时有更好的方法吗?

【问题讨论】:

堆栈溢出不适合征求意见。它适用于有关编程的特定技术问题。 “更好”和“正确”等短语不是客观衡量标准。 几乎没有理由动态分配std::vector。直接使用向量即可。您在向量中存储std::shared_ptr&lt;TaskTimer&gt; 而不仅仅是TaskTimer 是否有特殊原因? @Galik 感谢您让我意识到它们不需要动态分配。 【参考方案1】:

对于动态分配的对象来说,原始指针几乎总是错误的选择,因为它们不可避免地会导致内存泄漏和/或释放后使用错误。

所以唯一真正的决定是智能指针与值语义;答案很大程度上取决于您的 TaskTimer 类是如何实现的。

TaskTimer 是一个“轻量级”或“POD”对象,它非常便宜且易于复制吗?如果是这样,那么只需按值保存TaskTimer 对象(例如std::vector&lt;TaskTimer&gt;)就可以了。

OTOH,复制TaskTimer 对象的计算成本是否很高(甚至是编译时或运行时错误)?如果是这样,那么智能指针就是要走的路,因为这种方法将允许您的 TaskTimer 对象的生命周期比它们创建的范围更长。

【讨论】:

感谢您澄清我应该如何看待这一点。就我而言,TaskTimer 是一个由纯 C++ 和 POD 类型组成的轻量级计时器。我意识到我现在不需要动态分配它们:)

以上是关于保存计时器集合的最佳方法(对象与指针)的主要内容,如果未能解决你的问题,请参考以下文章

实现高分辨率计时器的最佳方法

C中的最佳计时方法?

JavaScript 日期与计时器

更新pyqtgraph的最佳方法?

在swift 3中保存变量和布尔值[关闭]

在另一个线程中独立计时 For 循环的每个滴答声的最佳方法