从此构建的std :: shared_ptr



我想将类的所有对象添加到std::map。由于我不想复制对象,因此我尝试使用这样的智能指针进行解决方法:

class.h

class A : public std::enable_shared_from_this<A> {
public:
    A();
    ~A();
    static std::map<uint32_t, std::shared_ptr<A>> getObjects();
private:
    static uint32_t counter;
    uint32_t id;
    static std::map<uint32_t, std::shared_ptr<A>> objects;
};

class.cpp

A::A()
{
    id = counter++;
    std::shared_ptr<A> ptr = std::make_shared<A>();
    objects[id] = ptr->shared_from_this();
}
A::~A()
{
    objects.erase(id);
}
std::map<uint32_t, std::shared_ptr<A>> A::getObjects()
{
    return objects;
}
uint32_t A::counter=0;
std::map<uint32_t, std::shared_ptr<A>> A::objects;

这可以很好地编译,但是当尝试像这样使用时

int main(){
    A a;
    A b;
    auto objects = A::getObjects();
}

我得到

分割故障:11`

如果我尝试将构造函数更改为

A::A()
{
    id = counter++;
    std::shared_ptr<A> ptr(this);
    objects[id] = ptr->shared_from_this();
}

我得到

释放的指针没有被分配

我基本上需要从this构建std::shared_ptr<A>,但无法设法使它起作用。

您的原始代码具有堆栈流:

A::A()
{
    id = counter++;
    std::shared_ptr<A> ptr = std::make_shared<A>();
    objects[id] = ptr->shared_from_this();
}

您在A的构造函数中无条件构造A

您尝试的方法也无法使用:

A::A()
{
    id = counter++;
    std::shared_ptr<A> ptr(this);
    objects[id] = ptr->shared_from_this();
}

shared_from_this()仅在此对象的寿命由std::shared_ptr管理时才能起作用。


您可以做些什么选择。您可以使用静态出厂功能而不会曝光构造函数,但这是您班级的意外设计。

对我来说似乎更清晰的设计是做类似于Pimpl模式的事情。您可以将std::shared_ptr s用于A的实际实现,并将功能包装在仅包含shared_ptr的对象中。

您无法获得没有共享指针管理对象的拥有的共享指针。

自动存储对象生命周期可能不会由共享指针管理其寿命。

通常,您的设计无法完成,因为对象和对象寿命由创建对象而不是对象本身的代码控制。

智能PIMPL包装器可以使对象的肠道具有单独的智能指针确定寿命。但是,即使在那里共享的指针解决方案也是非法的,因为破坏地图也可以杀死最后的共享指针,然后试图重新输入地图代码并删除它。这是未定义的行为。

薄弱的指针映射内容,基于PIMPL的包装器,消除实例的智能删除器以及其他工作可能会起作用。这超出了SO答案的范围。

您必须了解如何管理对象寿命,弱PTR的工作方式,替代删除器,基于PIMPL的值类型以及无数其他主题才能实现这一目标。祝你好运。

如果您需要存储在全局地图中的类的所有实例,则可以尝试以下操作:1)隐藏所有构造函数;2)仅通过静态("工厂")方法创建新对象。在您的情况下,此方法可以返回 shared_ptr(或者说,它可以返回参考,共享_ptr本身私有为全局地图;在这种情况下,您甚至可以使用unique_ptr)。

相关内容

  • 没有找到相关文章

最新更新