当引用计数达到0时,std::shared_ptr会破坏它正在管理的对象。但是,我正在寻找一种智能指针,当引用计数降到2以下时,对象就会被销毁。是否有这样的智能指针(或者可以使智能指针以安全的方式运行)?
用例场景:我正在建模一个连接。连接由它所连接的两个端点所拥有(如“智能指针的所有权”中的那样)。一旦其中一个端点被破坏,连接也应该被销毁。
我知道我可以在适当的析构函数中使用经典的delete语句来实现这一点(因为在这种情况下,我对“低于2”的要求非常容易)。但我认为这是一种智能指针的有效用例,我很想看看我是否可以用一种现代的方式来做这件事。
发布于 2016-08-24 10:42:39
可能最简单的解决方案是,每一方都有一个指向对象的shared_ptr,一个指向对象的weak_ptr,以及一个指向另一端的shared_ptr的常规指针。
要访问该对象,请锁定weak_ptr。如果失败,对象就会消失。
要想摧毁自己,您可以锁定weak_ptr,通过指向它的常规指针重置对方的shared_ptr,重新设置您自己的shared_ptr,然后去掉weak_ptr锁的结果。
或者,您可以只使用计数器和常规指针。如果计数器是1,你知道另一边不见了,所以你可以直接销毁这个物体。
发布于 2016-08-27 00:28:45
谢谢你把你想要达到的效果包括在内。
您不需要或不需要智能指针中的任何特殊逻辑。两端都需要对共享对象的普通强引用。这清楚地表明,只要任何一方都知道它的存在,它就会生存。
相反,您需要的是一个事件通知,其中任何一方都可以在其离开时通知另一方。然后幸存的一方可以干净地进行适当的清理,包括将其(现在是最后一个) shared_ptr设置为null,但也可以执行逻辑上需要的任何其他操作。
发布于 2016-08-24 13:49:37
因为你有两个主人,当他们两个都死了,你想杀了它,我可能会这样做:
template<class T>
struct shared_connection {
// by default, kill the connection if we are connected:
~shared_connection() {
sever();
}
// wrap a shared pointer to the connection data:
shared_connection( std::shared_ptr<T> p ):
ptr(std::make_shared<std::shared_ptr<T>>(std::move(p)))
{}
// create a new connection:
shared_connection fork() const {
return {ptr};
}
// an even more explicit move:
shared_connection transfer() {
return std::move(*this);
}
friend void swap( shared_connection& lhs, shared_connection& rhs ) {
std::swap( lhs.ptr, rhs.ptr );
}
// move only type:
shared_connection(shared_connection&& src)
{
swap(*this, src);
};
shared_connection& operator=(shared_connection&& src)
{
auto tmp = std::move(src);
swap(*this, tmp);
return *this;
};
// lock it for use. The connection can die
// but the data will persist until the lock ends:
std::shared_ptr<T> lock() const {
if (!ptr) return {}; // don't break if we have been abandon()ed
return atomic_load(ptr.get());
}
// do not kill the connection:
void abandon() {
ptr = {};
}
// kill the connection:
void sever() {
atomic_store(ptr.get(), std::shared_ptr<T>{});
abandon();
}
// please just lock instead of calling this:
explicit operator bool() const {
return (bool)lock();
}
private:
std::shared_ptr<std::shared_ptr<T>> ptr;
};
template<class T, class...Args>
shared_connection<T> make_shared_connection( Args&&... args ) {
return std::make_shared<T>(std::forward<Args>(args)...);
}首先,通过一个shared_connection创建一个std::make_shared<T>。
然后把它.fork()给另一方。当任何一个shared_connection都消失时,内部T就会被销毁,除非其中一个shared_connection已经对其进行了.lock()编辑。
我认为我的原子代码是正确的,所以它支持连接的两边处于不同的线程中。它还应该支持多党关系。
第一个共享指针表示连接解锁生存期的共享控件。第二个共享指针表示在短操作期间保持连接的能力。
.abandon()允许某人在不切断连接的情况下断开连接。.sever()允许您在不破坏对象的情况下销毁共享连接数据。
代码未被测试。
如果希望连接的每一方在共享连接结束时在一堆代码中共享所有权,则执行指向该共享连接的共享指针。因为没有什么能说爱就像共享指针指向共享指针一样。
我们还可以通过阻止应用程序中对它的访问来避免内部共享指针“泄漏”的可能性:
template<class F, class R=std::decay_t<std::result_of_t<F(T const&)>>>
std::optional<R> read( F&& f ) const {
auto p = lock();
if (!p) return {};
T const& t = *p;
return std::make_optional<R>( std::forward<F>(f)(t) );
}
template<class F, class R=std::decay_t<std::result_of_t<F(T&)>>>
std::optional<R> write( F&& f ) const {
auto p = lock();
if (!p) return {};
T& t = *p;
return std::make_optional<R>( std::forward<F>(f)(t) );
}通过使用上述方法替换公共.lock()。
https://stackoverflow.com/questions/39120972
复制相似问题