2

妙用 std::optional 类简化状态机设计

 1 year ago
source link: https://netcan.github.io/2022/05/16/%E5%A6%99%E7%94%A8-std-optional-%E7%B1%BB%E7%AE%80%E5%8C%96%E7%8A%B6%E6%80%81%E6%9C%BA%E8%AE%BE%E8%AE%A1/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

妙用 std::optional 类简化状态机设计

2022.05.16

Netcan

编程

 热度 ℃

一些类可能存在和生命周期相关的状态,例如该类中常常包含着 StartStop等接口,通常而言,对象被构造动作相当于做初始化,而 Start 方法才真正干活,例如创建线程,然后 Stop 方法去停掉线程,那么对于析构函数而言,除了本身需要销毁的那部分动作外,还需要检查 Start 的状态,以便判断是否需要Stop

一旦引入 StartStop等接口,意味着该类的作者需要追踪这个类的状态,并且这个类的每个接口可能都需要判断这个状态,总之,他需要考虑的因素也多了些:

  • 如果用户重复 Start 怎么办?
  • 如果用户仅仅 Stop 怎么办?
  • 某个接口调用的时候,是否需要保证 Start 状态?如果没有怎么处理?
  • 析构行为需要考虑 Start 状态

如果将 Start 的语义收编到构造函数,Stop语义收编到析构函数,那么因为该状态的消除意味着复杂度也降了很多,代码因此也就很简洁。如果用户仍然需要延迟 Start 的语义,那么可以交由类 std::optional 组合而成,例如在需要 Start 的地方使用 emplace 接口构造出该对象,在需要 Stop 的地方使用 reset 接口销毁对象:

class UserObj {
    // ...
private:
    // 使用 optional 表达额外的 Start/Stop 语义
    std::optional<Thread> m_thread;
};

std::optional<Thread>类由 C++17 标准引入,它相当于组合了状态类与标记字段,并且无需动态分配内存,可以理解大小为 sizeof(Thread) + sizeof(bool),这要比使用unique_ptr<Thread> 的方式要高效的多。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK