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

调用std::function期间释放其所在std::optional是否符合C++20标准?

在std::function执行期间清除其所在std::optional的行为是否符合C++20标准?

我在C++标准中未找到明确答案,想确认当前操作是否为定义良好的行为。我有一个代表线程的类,其中包含成员std::optional<std::function<void()>> ops;线程空闲时会检查ops是否有值,若有则执行(已做适当锁保护)。我想知道:从当前加载到ops中的function内调用ops.clear()是否属于定义良好的行为?

以下是更具说明性的示例(无线程但保留锁机制):

class ops_t
{
  private:
    std::mutex mutex;
    std::optional<std::function<void()>> ops;
  public:
    void set_ops(std::function<void()> new_ops)
    {
      std::lock_guard guard(mutex);
      ops = new_ops;
    }

    void clear_ops()
    {
      std::lock_guard guard(mutex);
      ops.reset();
    }

    void do_ops()
    {
      std::optional<std::function<void()>> ops_local = [this]() // make copy so we don't hold mutex while executing
      {
        std::lock_guard guard(mutex);
        return ops;
      }();
      if(ops_local)
        (*ops_local)();
    }
};


int main(void)
{
  ops_t ops;
  ops.set_ops(std::bind_front(&ops_t::clear_ops, &ops));
  ops.do_ops(); // is the sequence of events triggered here well defined by the standard?
}

StackOverflow上的相关帖子并未解答我的问题,其Accepted Answer主要讨论对象被删除后的指针问题,而我不存在该问题。此代码编译运行无段错误,但场景特殊,需确认是否符合C++20标准。


结论:该行为是C++20标准下定义良好的

核心依据:

  • 执行的是独立的std::function拷贝:在do_ops中,我们先通过加锁拷贝了成员变量ops到局部变量ops_local,后续执行的是这个局部拷贝的std::function。原成员变量ops中的std::function与局部拷贝是完全独立的对象,前者的销毁(通过reset())不会影响后者的执行。
  • std::optional::reset()的合法行为:std::optional::reset()的作用是销毁其内部包含的对象(若存在),这是标准明确允许的操作,只要被销毁的对象不是当前执行流的直接依赖——这里我们执行的是局部拷贝,原对象的销毁不会干扰正在运行的函数逻辑。
  • 无数据竞争:所有对成员变量ops的访问(拷贝、重置)都通过std::mutex加锁保护,符合C++标准中关于线程安全的要求(即使示例中没有多线程,锁的使用也保证了对ops的操作是原子性的,不存在未定义的并发访问)。

另外,std::function的拷贝语义保证了局部的ops_local持有可调用对象的独立副本(这里是std::bind_front生成的绑定对象的拷贝),所以在执行该副本的过程中,原成员变量中的std::function被销毁,不会对当前执行的函数造成任何影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:22:51