假设我有一个对象 - 我们将它称为Obj--我希望它包含一个指向它自己类型的实例的静态指针。例如:
class Obj{
static auto get_active_obj() -> const Obj*;
auto make_active_obj() -> void;
private:
static const Obj* active;
};
现在,在这种情况下使用智能指针,特别是shared_ptr是不错的做法?这里使用shared_ptr的想法是,当用户使用get_active_obj查询对象时,我只能将weak_ptr返回给活动对象,用户可以查询它以检查活动对象是否已更改/仍然有效。现在,问题是,这是最优化(甚至可行)的解决方案吗?例如:
class Obj{
static auto get_active_obj() -> std::weak_ptr<const Obj>;
auto make_active_obj() -> void;
private:
//another concern with this is that I have to provide a "no-OP"
//deleter to prevent a segfault when the shared_ptr tries to delete a static
//pointer.
static std::shared_ptr<const Obj> active;
};
int main(){
Obj o;
o.make_active_obj();
auto active = Obj::get_active_obj();
if(active.expired()){ //is it still active?
auto active_obj = active.lock();
//do stuff
}
}
make_active_obj()的概念实现:
auto make_active_obj()const -> void {
active.reset(this);
}
析
~Obj(){
if(this == active.get())
active.reset();
}
答案 0 :(得分:4)
我会在你的程序中反转使用shared和weak_ptr。那就是:我会使用静态weak_ptr
来保存对当前活动对象的引用,但只要有人调用shared_ptr
以便使用它就会返回get_active_obj()
。
class Obj{
static std::shared_ptr get_active_obj();
void make_active_obj();
private:
static std::weak_ptr<const Obj> active;
};
int main(){
Obj o;
o.make_active_obj();
auto active = Obj::get_active_obj();
if(active){ //is it still active?
//do stuff
}
}
原因是您可能希望能够销毁/关闭活动对象,而无需在此之前激活其他对象(例如,在终止程序之前)。
这也更适合程序的语义:当某个函数想要使用活动对象时,必须确保在处理对象时不会销毁该对象,因此这是一个(临时)拥有关系。另一方面,类可能并不关心对象是否被销毁,因为它只提供对程序其他部分的引用,因此这是一种非拥有关系。
答案 1 :(得分:1)
在某些代码调用get_active_obj()
后应该删除活动对象吗?由于您的对象似乎在堆栈中,答案显然是否定的。因此,get_active_obj()
应该绝对不返回拥有指针。我会这样做:
class Obj{
static const Obj* get_active_obj() {return active;}
void make_active_obj() const {active = this;}
~Obj() {if (active==this) active=nullptr;}
private:
static const Obj* active;
};
由于get_active_obj()
的收件人不拥有Obj
,他们所需要的只是一个指针。 (它将是一个引用,但你不能有一个可空引用,所以它是指针。另请注意,当调用Obj
的析构函数时,它使自己不再是活动指针。简单。
当然,这个答案是100%基于你的Obj
在堆栈上或以其他方式管理的事实。如果您希望make_active_obj
分享所有权,请参阅其他答案。