如何管理"shortest of"类型的生命周期?
How to manage lifetime of the type "shortest of"?
当一个对象有一个父对象时,我们使用复合,父对象应该关心对象的生命周期。在同样的情况下,我们使用unique_ptr
,但对象可以是nullptr
。
当几个外部实体可能需要我们的对象时,我们使用shared_ptr
,因此它的生命周期被延长,直到最后一个外部实体失去兴趣。
这里我想问另一个生活中的情况。如果对象需要在几个持续时间中最短,该怎么办?
下面是一个例子。让我们有一个一次性计时器,它存储一个函子并在计数完成后执行它。这对我来说是有意义的*,这个计时器对象在:
之后被销毁:1. fulfilling its task - therefore it should be able to destroy istelf
or
2. the parent loosing interest in the timer - so the parent should be able to
destroy the object as well
目前,我使用唯一指针的笨拙实现。这个问题的一个好的模式/指导方针/实现是什么?
*原因:1)函子可能拥有其他资源2)计时器可能已经设置为一个非常大的数字,然后放弃3)如果父类已经被销毁,我们一般不想调用它的回调
这里存在严重的并发性和重入性问题。
当两个或两个以上的代码都有权删除一个指针时,任何一个代码都不能可靠地解引用该指针,因为在解引用时,另一个代码可能会销毁该指针。
同样地,任何你检查你拥有所有权的分支都可能在任何其他非本地(比如函数调用)运行的时候变得陈旧,即使没有并发性。
我们可以绕过这些。
template<class T>
struct shared_destroyable {
std::shared_ptr<T> lock() const {
return atomic_load<T>(ptr.get());
}
explicit operator bool() const { return (bool)lock; }
void reset( std::shared_ptr<T> pin = {} ) {
atomic_store(ptr.get(), std::move(pin));
}
shared_destroyable(std::shared_ptr<T> pin):
ptr(std::make_shared<std::shared_ptr<T>>(std::move(pin))
{}
shared_destroyable()=default;
shared_destroyable(shared_destroyable&&)=default;
shared_destroyable(shared_destroyable const&)=default;
shared_destroyable& operator=(shared_destroyable&&)=default;
shared_destroyable& operator=(shared_destroyable const&)=default;
private:
std::shared_ptr<std::shared_ptr<T>> ptr;
};
这表现得像weak_ptr
shared_ptr
的混合。
如果最后一个消失了,对象被销毁。
然而,如果它们中的任何一个是.reset()
,那么只要最后一个具有lock()
ed的代码结束了的作用域,该对象就会被销毁。
所引用的赋值变化
所以在使用时,你可以这样做:
if(auto sp = sd.lock()) {
// use sp
}
和sp
的生命周期保证在{}
的范围内持续,即使有人在块内,在另一个线程中,或者当您调用其他一些方法时执行sd.reset()
。
我认为最好的解决方案是有一个包装器对象,它有一个指向实际计时器对象的唯一指针,以及一个计时器对象的getter,如果它已被销毁,则返回null。
这样,如果计时器过期并被销毁,没有失去兴趣的调用者不会留下一个表面上有效但实际上无效的指向计时器对象的指针。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 如何管理"shortest of"类型的生命周期?
- c++概念生命和类型别名声明