我想将类的所有对象添加到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)。