首页 > 解决方案 > unique_ptr 作为通用处置对象

问题描述

假设我有一个情况,我有一个 SDK,它提供了某些接口,这意味着一些手动资源管理或状态更改。它应该像这样使用:

// SDK has state B by default
SDK->setStateA();
something();
requiring();
stateA();
SDK->setStateB();

将状态更改封装为 unique_ptr 对象的自定义分配器/删除器是一个好主意,或者,最好通过一些手动 Dispose 模式实现来获得这种行为。

由于这不是资源分配,我有疑问。它可能会引起混乱并使代码变得神秘。

我的另一个担心是我需要从初始化和清理步骤中返回代码。我可以使用 lambdas 并通过捕获来获取它们,但它看起来更加神秘。

也许有人已经尝试过了,并看到它在一段时间后如何使代码看起来?

标签: c++c++11design-patternsunique-ptrdispose

解决方案


一般来说,最好将代码的界面设计成易于使用和直观的方式,或者换句话说,很难错误地使用它。特别是如果接口能够通过拒绝编译来防止bug,可以节省大量的调试时间。

实现这种接口的一种可能性是与std::mutex<--->std::unique_lock机制松散相关的东西:

class state_guard {
   std::unique_ptr<SDK_type>& SDK;

   state_guard(std::unique_ptr<SDK_type>& s) : SDK{ s } {
       SDK->setStateA();
   }

   ~state_guard() {
       SDK->setStateB();
   }
};

void something(state_guard&, ...);
void requiring(state_guard&, ...);
void stateA(state_guard&, ...);

std::unique_ptr<SDK_type> SDK{ get_sdk() };
{
   state_guard guard{ SDK };
   something(guard, ...);
   requiring(guard, ...);
   stateA(guard, ...);
}

通过强制将守卫作为函数参数传递(即使它在相应的函数中未使用),用户不会忘记设置为 stateA(并且感谢 RAII,将其重置为 stateB)。


推荐阅读