C++ 将std::shared_ptr转换为QPointer

C++ 将std::shared_ptr转换为QPointer,c++,c++11,shared-ptr,qpointer,C++,C++11,Shared Ptr,Qpointer,我们的应用程序设计得非常糟糕-它使用std::shared_ptr和QObject父子关系来管理我们的一些对象。当QObject::~QObject删除其子对象,然后shared\u ptr尝试将其删除时,这会导致segfaults 我们讨论过这一点,但目前还没有办法轻松修复,所以在修复之前,我需要使用一些肮脏的黑客 现在我有了一个std::shared\u ptr getMyObjectPtr()函数。我需要将结果放入QPointer-QPointer是弱指针,仅指示它们管理的QObject是

我们的应用程序设计得非常糟糕-它使用
std::shared_ptr
QObject
父子关系来管理我们的一些对象。当
QObject::~QObject
删除其子对象,然后
shared\u ptr
尝试将其删除时,这会导致segfaults

我们讨论过这一点,但目前还没有办法轻松修复,所以在修复之前,我需要使用一些肮脏的黑客

现在我有了一个
std::shared\u ptr getMyObjectPtr()
函数。我需要将结果放入
QPointer
-QPointer是弱指针,仅指示它们管理的QObject是否被删除。我不能以任何方式更改该函数,它会破坏整个应用程序

我尝试了一些自定义dealocator的破解,但似乎不起作用

// get the shared_ptr from inacessible API
std::shared_ptr<MyObject> oldPtr(getMyObjectPtr());
// create a new pointer that never deletes it's value
std::shared_ptr<MyObject> newPtr(nullptr, [](MyObject*) {});
// Move pointer from old to new non-deleting ptr
newPtr.swap(oldPtr);
QPointer<MyObject> qptr(newPtr.get());
//从不可访问的API获取共享的\u ptr
std::shared_ptr oldPtr(getMyObjectPtr());
//创建一个从不删除其值的新指针
std::sharedptrnewptr(nullptr,[](MyObject*){});
//将指针从旧移到新非删除ptr
新PTR.掉期(旧PTR);
QPointer-qptr(newPtr.get());

然而,这样一来,一旦我的函数结束,指针就会被删除。据推测,自定义解除分配程序会随数据一起移动。

我认为除了开始重构代码,以便通过QObject样式的父/子关系或共享\u ptr引用计数管理任何给定对象之外,没有任何好的解决方案,但决不能在同一个对象中同时进行。这两种方法相差太大,很难调和

也就是说,为了完成上述任务而不需要太多的重新设计,您可以做的一件事是:不要让共享的ptr指向您的QoObject,而是让共享的ptr指向QoObject的一个(基于非QoObject的)共享的ptr管理子对象

也就是说,与此相反:

class MyQObject : public QObject 
{
public:
   MyQObject(int x, int y, int z, QObject * parent)
      : QObject(parent), m_x, m_y, m_z {/* empty */}

   int getX() const {return m_x;}
   int getY() const {return m_y;}
   int getZ() const {return m_z;}

private:
   int m_x, m_y, m_z;
};

[...]

QObject * parent = new QObject;
shared_ptr<MyQObject> ptr(new MyQObject(1,2,3,parent));   // d'oh!  trouble!
MyQObject类:公共QObject { 公众: MyQObject(int x、int y、int z、QObject*父对象) :QObject(父对象),m_x,m_y,m_z{/*empty*/} int getX()常量{return m_x;} int getY()常量{return m_y;} int getZ()常量{return m_z;} 私人: int m_x,m_y,m_z; }; [...] QObject*父对象=新QObject; 共享_ptr ptr(新的MYQoObject(1,2,3,父级));//哦!麻烦 这样做:

class MyData
{
public:
   MyData(int x, int y, int z) : m_x(x), m_y(y), m_z(z)

   int getX() const {return m_x;}
   int getY() const {return m_y;}
   int getZ() const {return m_z;}

private:
   int m_x, m_y, m_z;
};

class MyQObject : public QObject
{
public:
   MyQObject(int x, int y, int z, QObject * parent)
      : QObject(parent), m_data(make_shared<MyData>(x,y,z)) {/* empty */}

   int getX() const {return m_data->getX();}
   int getY() const {return m_data->getY();}
   int getZ() const {return m_data->getZ();}

   shared_ptr<MyData> getData() {return m_data;}

private:
   shared_ptr<MyData> m_data;
};

[...]

QObject * parent = new QObject;
QObject * myObj = new MyQObject(1,2,3,parent));
shared_ptr<MyData> ptr(myObj->getData());   // no problem!
类MyData
{
公众:
MyData(int x,int y,int z):m_x(x),m_y(y),m_z(z)
int getX()常量{return m_x;}
int getY()常量{return m_y;}
int getZ()常量{return m_z;}
私人:
int m_x,m_y,m_z;
};
类MyQObject:公共QObject
{
公众:
MyQObject(int x、int y、int z、QObject*父对象)
:QObject(父对象),m_数据(使_共享(x,y,z)){/*empty*/}
int getX()常量{return m_data->getX();}
int getY()常量{return m_data->getY();}
int getZ()常量{return m_data->getZ();}
共享的\u ptr getData(){return m\u data;}
私人:
共享的ptr m_数据;
};
[...]
QObject*父对象=新QObject;
QObject*MyObject=新的MyQObject(1,2,3,父对象);
共享_ptr ptr(myObj->getData());//没问题!

这样,您的Qt样式代码可以访问QObject和MyData,而共享的_ptr样式代码可以访问MyData。(当然,如果您的共享_ptr样式代码还需要访问QObject本身,那么您可能运气不佳,因为Qt将决定何时何地删除QObject,并且不尊重共享_ptr语义)

一次又一次地添加黑客听起来是个不错的主意,但据我所知,您试图做的实际上是获取原始指针,并告诉
共享\u ptr
它不再对此负责,就像,正确吗?AFAICT这是不可能的-使用
std::make_shared
制作的
shared_ptr
在控制块内分配了对象本身,因此不可能从中获得“自由”、“正常”可删除的
T*
。恐怕您必须修改您的代码> GETMyObjutpTrp/代码>。如果这个代码的实例> SydDypTr> /Cudio >实际上是<代码> UNQuijPPTR <代码>(这意味着它不与任何人共享所有权),您可以考虑从<代码> SyddYPPT的所有权中移动这个<代码> MyObjult实例。在这种情况下,QPointer将指向moved to instance,而
shared_ptr
将指向MyObject的moved from instance。如果这对您有任何意义的话,我可能会在下面的答案中详细说明。@iehrlich:
QObject
不支持移动。@iehrlich:当然,我不是在批评一般方法,只是指出为什么它们在OP is的情况下无法工作。:-)顺便说一下,Qt不是一个坏的世界,而且IHO肯定是唯一的严重的跨平台C++ GUI工具包——但是,你必须比java(或C++)更像Java或.NET(尤其是对象模型)。