c++ 不需要对象重新分配/移动操作的标准库容器?

qjp7pelc  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(115)

我围绕FreeRTOS定时器API构建了一个C++ Package 器。我的类静态分配定时器控制块,该控制块由FreeRTOS线程在后台操作。这意味着如果我移动或复制此对象,控制块也将被移动/复制,但线程不会注意到这一点。因此,我认为该对象不可复制和不可移动。
以下是大纲:

#include <cstdint>
#include <concepts>

template <std::invocable Cb>
class timer
{
public:
    timer() = default;
    timer(Cb cb, TickType_t timer_period, bool auto_reload = false)
        : cb_{ cb }
    {
        xTimerCreateStatic("timer", timer_period, auto_reload, static_cast<void*>(this), &timer::timer_expired_cb, &buf_);
    }

    timer(const timer&) = delete;
    timer(timer&&) = delete;
    auto operator=(const timer&) = delete;
    auto operator=(timer&&) = delete;
    // ...
private:
    Cb cb_;
    TimerHandle_t handle_;
    StaticTimer_t buf_;
};

现在我想把多个这个定时器对象推入一个C++容器,当对象进入或离开容器时,我可以动态地扩展或收缩容器。有没有一个stdlib容器不要求对象是可移动或可复制的,但仍然提供所有功能?

vxbzzdmp

vxbzzdmp1#

我看到四个基本选项:

  • std::list<timer>:这可能是非常罕见的情况之一,此时使用std::list是最佳选择。插入到列表中必须通过一个emplace成员函数来完成,因为你不能在一个已经存在的对象中移动。
  • std::vector<std::unique_ptr<timer>>:如果timer对象的构造与将它们保存在容器中没有直接关系。这样做的缺点是访问和删除条目比std::list稍微多一些。但是你的timer工厂不需要知道你打算如何存储对象。
  • std::set<timer>:你说你有新的对象到达和离开。如果你有很多对象,也许你想避免find把它们放在一个线性容器中。std::set也没有重新分配,并为你提供了一个很好的界面来查找和擦除对象。但很明显,它比其他两个建议有更多的开销。
  • std::array<std::optional<timer>, N>:如果你知道在运行时你能看到的最大计时器数N,考虑一个固定大小的数组,其中包含可选项。它没有指针间接寻址,但在搜索一个项时可能会有很多分支。

相关问题