我们的应用程序设计非常糟糕 - 它使用std::shared_ptr
和QObject
父子关系来管理我们的一些对象。当QObject::~QObject
删除其子对象时,这会导致段错误,然后shared_ptr
也会尝试删除它们。
我们已经讨论了这个问题,但目前看不到任何方法可以轻松解决这个问题,所以在修复之前我需要使用一些脏黑客。
现在我拥有的是std::shared_ptr<MyObject> getMyObjectPtr()
功能。我需要将结果放入QPointer<MyObject>
- QPointers是弱指针,仅指示它们管理的QObject是否被删除。我不能以任何方式改变这个功能,它会破坏整个应用程序。
我尝试了一些使用自定义处理程序的黑客攻击,但这似乎不起作用。
// 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());
但是这样,一旦我的函数结束,指针就会被删除。据推测,自定义分配器与数据一起移动。
答案 0 :(得分:0)
除了开始重构代码以便通过QObject样式的父/子关系或 shared_ptr&lt;&gt;引用计数 - 但从不在同一个对象中。这两种方法彼此之间的差异太大,不易调和。
那就是说,为了在没有太多重新设计的情况下完成上述操作,您可以做的一件事就是:不要使用shared_ptr&lt;&gt;将指向您的QObject,使shared_ptr指向QObject的(基于非QObject),shared_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!
做这样的事情:
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!
这样你的Qt风格代码就可以访问QObject和MyData,而shared_ptr风格的代码可以访问MyData。 (当然,如果你的shared_ptr风格的代码也需要访问QObject本身,你可能会运气不好,因为Qt将决定删除QObject的时间和地点,并且不会尊重shared_ptr语义)