c++ - unique_ptr 作为通用处置对象
问题描述
假设我有一个情况,我有一个 SDK,它提供了某些接口,这意味着一些手动资源管理或状态更改。它应该像这样使用:
// SDK has state B by default
SDK->setStateA();
something();
requiring();
stateA();
SDK->setStateB();
将状态更改封装为 unique_ptr 对象的自定义分配器/删除器是一个好主意,或者,最好通过一些手动 Dispose 模式实现来获得这种行为。
由于这不是资源分配,我有疑问。它可能会引起混乱并使代码变得神秘。
我的另一个担心是我需要从初始化和清理步骤中返回代码。我可以使用 lambdas 并通过捕获来获取它们,但它看起来更加神秘。
也许有人已经尝试过了,并看到它在一段时间后如何使代码看起来?
解决方案
一般来说,最好将代码的界面设计成易于使用和直观的方式,或者换句话说,很难错误地使用它。特别是如果接口能够通过拒绝编译来防止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)。
推荐阅读
- python - 如何批量更新 Google Cloud Functions 中的 requirements.txt 文件
- swift - 在隐式展开可选值时意外发现 nil:无法解决
- postgresql - .sql 文件中的 \i '/docker-entrypoint-initdb.d/tables/users.sql' 显示错误。不知道为什么
- c++ - 初始化列表、参数包扩展、折叠表达式和求值顺序
- azure - Azure Function AppSettings 使用 Terraform 和多个地图源
- java - 为什么继承在这里不能正常工作?扩展 Java 类中的方法没有给我想要得到的结果
- javascript - 在 React 中更改背景图片的 URL
- javascript - 使用 for 循环时,如何在开始另一次提取之前等待一次提取完成?
- c++ - 我想在激活缓冲区后使用 cin 或 cout 。我应该怎么办
- python - 如何在 postgresql 数据库中导入 geojson 文件?