Convert std :: shared_ptr to QPointer

Our application is very poorly designed - relations std::shared_ptrand QObjectparent-child are used to control some of our objects . This results in segfaults when it QObject::~QObjectdeletes its children, and THEN shared_ptralso tries to delete it.

We discussed this, but at the moment we see no way to fix it easily, so I will need to use some dirty hacks until we fix it.

Now I have a function std::shared_ptr<MyObject> getMyObjectPtr(). I need to put the result in QPointer<MyObject>- QPointers are weak pointers that simply indicate whether the QObject they are deleting is deleted. I cannot change this function in any way, it will break the whole application.

I tried several hacks with a custom dealer, but this does not work.

// get the shared_ptr from inacessible API
std::shared_ptr<MyObject> oldPtr(getMyObjectPtr());
// create a new pointer that never deletes it 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());

However, in this way, the pointer is deleted after the completion of my function. Presumably, a custom dealocator moves along with the data.

+4
source share
1 answer

I don’t think there is a good solution to this problem, except to start refactoring your code so that any given object is controlled through parent / child relations like QObject, or shared_ptr <> reference counting, but never in both objects. These two approaches are too different from each other to easily come to terms.

, , , , : , shared_ptr < > , QObject, shared_ptr (- QObject), -, shared_ptr QObject.

:

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)

0

Source: https://habr.com/ru/post/1680632/


All Articles