我想将类的所有对象添加到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.h
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;
Class.cpp
int main(){
A a;
A b;
auto objects = A::getObjects();
}
这个编译很好但是当试图像这样使用它时
A::A()
{
id = counter++;
std::shared_ptr<A> ptr(this);
objects[id] = ptr->shared_from_this();
}
我得到了
分段错误:11`
如果我尝试将构造函数更改为
std::shared_ptr<A>
我得到了
释放的指针未分配
我基本上需要从this
构建一个SELECT SUM(DETA_MTO_CUOTA) MONTO, DETA_NACIONALIDAD as NAC,
DETA_CEDULA as CEDULA, DETA_CODIGO as CODIGO,
DETA_SUB_CODIGO as SUBCODIGO, DETA_AJUN_ANO_FISCAL as FISCAL
FROM SRH_DETALLE_AJUS
WHERE DETA_AJUN_NRO = 6351 AND
DETA_TIPO_REG = 'A' AND
DETA_SUB_CODIGO = 50
GROUP BY DETA_NACIONALIDAD, DETA_CEDULA, DETA_CODIGO, DETA_SUB_CODIGO, DETA_AJUN_ANO_FISCAL
,但无法让它工作。
答案 0 :(得分:1)
您无法获得指向不受共享指针管理的对象的拥有共享指针。
自动存储对象的生命周期可能没有由共享指针管理其生命周期。
通常,您的设计无法完成,因为对象和对象的生命周期由创建对象的代码控制,而不是对象本身。
智能pImpl包装器可以使对象的内容具有单独的智能指针确定的生命周期。但即使存在共享指针解决方案也是非法的,因为销毁地图可以杀死最后一个共享指针,然后该指针尝试重新输入地图代码并将其删除。这是未定义的行为。
弱指针映射内容,基于pImpl的包装器,取消注册实例的智能删除器以及其他工作的混合可能有效。这超出了SO答案的范围。
您必须了解如何管理对象生命周期,弱ptrs的工作方式,替代删除器,基于pImpl的值类型以及无数其他主题。祝你好运。
答案 1 :(得分:1)
您的原始代码有堆栈溢出:
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
实现A
的实际实现,并将功能包装在仅包含shared_ptr
的对象中。
答案 2 :(得分:1)
如果您需要存储在全局映射中的类的所有实例,可以尝试以下操作:1)隐藏所有构造函数; 2)仅通过静态('工厂')方法创建新对象。在您的情况下,此方法可以返回shared_ptr
(或者说,它可以返回引用,shared_ptr本身专用于全局映射;在这种情况下,您甚至可以使用unique_ptr)。