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

时间:2018-08-23 04:04:45

标签: c++ pointers vector timer

我一直在尝试为chrono的high_performance_clock实现包装类。基本上,有一个Diagnostics母类,其中包含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集合现在是否最适合性能?在保留当前功能的同时,还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

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

因此,唯一真正的决定是智能指针与价值语义;答案将很大程度上取决于TaskTimer类的实现方式。

  • TaskTimer是“便宜”或“ POD”的对象,它非常便宜且易于复制吗?如果是这样,那么只需按值保存TaskTimer个对象(例如std::vector<TaskTimer>)即可。

  • OTOH,复制TaskTimer对象的副本在计算上是否昂贵(甚至是编译时或运行时错误)?如果是这样,那么智能指针便是可行的方法,因为这种方法将使您的TaskTimer对象的生存期比在其创建范围内的生存期更长。