You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

适配不可拷贝移动timer类的C++标准库容器选型咨询

问题背景与需求

我基于FreeRTOS定时器API封装了一个C++类,该类静态分配由后台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_;
};

现在我想将多个此类timer对象存入可动态扩展或收缩的C++标准库容器,是否存在无需对象可移动或可拷贝的符合要求的容器?

解决方案

有两种可行的方案,不需要修改timer类的不可拷贝/不可移动特性:

1. 存储智能指针的标准容器

所有支持动态扩展的C++标准容器(比如std::vector、std::list、std::deque)都可以存储智能指针,推荐用std::unique_ptr<timer<Cb>>(独占所有权)或std::shared_ptr<timer<Cb>>(共享所有权):

  • 智能指针本身支持移动(std::unique_ptr)或拷贝+移动(std::shared_ptr),容器扩展时只会操作指针,不会触碰底层的timer对象,完全规避了拷贝/移动timer实例的风险。
  • 示例代码:
    // 定义存储unique_ptr的vector
    std::vector<std::unique_ptr<timer<MyCallbackFunc>>> timer_list;
    // 原地创建timer并加入容器
    timer_list.emplace_back(std::make_unique<timer<MyCallbackFunc>>(
        [](){ /* 定时器回调逻辑 */ }, 
        pdMS_TO_TICKS(1000), 
        true
    ));
    

2. 使用std::vector<std::optional<timer<Cb>>>(C++17+)

如果希望直接存储对象而非指针,可以用std::optional包装timer后存入std::vector:

  • std::optional允许容器中存在空位置,你可以通过emplace在容器的空位置原地构造timer对象,全程不会触发timer的拷贝或移动操作。
  • 示例代码:
    std::vector<std::optional<timer<MyCallbackFunc>>> timer_list;
    // 预分配容器空间
    timer_list.resize(3);
    // 在指定位置原地构造timer
    timer_list[0].emplace(
        [](){ /* 回调逻辑 */ }, 
        pdMS_TO_TICKS(500), 
        false
    );
    // 直接追加一个构造好的optional对象
    timer_list.emplace_back(std::in_place, [](){}, pdMS_TO_TICKS(2000), true);
    

关键注意点

  • 无论采用哪种方案,都要保证timer对象的生命周期不短于后台FreeRTOS线程的生命周期,避免出现悬垂引用或无效定时器控制块。
  • 务必在timer类的析构函数中调用xTimerDelete清理FreeRTOS定时器资源,防止内存泄漏。

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 21:25:17