Должен ли я удалить QPointer в деструкторе класса? - PullRequest
1 голос
/ 04 мая 2019

Предположим, у меня есть класс, подобный следующему:

#include <Object>
#include <QProcess>

class MyClass: public QObject {
private:
    QPointer<QProcess> m_process{ nullptr };
public:
    MyClass(QObject *parent = nullptr)
        : QObject{ parent }
        , m_process{new QProcess{} }
    {
        QObject::connect(m_process, &QProcess::errorOccurred,
            this, [](QProcess::ProcessError error) {
            qDebug() << "error: " << error;
            });
    }
    ~MyClass()
    {
        if (m_process)  delete m_process; //--> is it necessary?
    }
};

Нужно ли мне удалять m_process вручную , как показано в деструкторе?

К сожалению, я не могу использовать std::unique_ptr или std::shared_ptr, поскольку

QObject::connect(m_process, &QProcess::errorOccurred,
            this, [](QProcess::ProcessError error) {
            qDebug() << "error: " << error;
            });

Я не видел надлежащей перегрузки для QObject::connect.

С другой стороны, в QPointer :: ~ QPointer () Я прочитал:

Уничтожает охраняемый указатель.Как и обычный указатель, уничтожение защищенного указателя не уничтожает объект, на который указывают.

Это означает, что QPointer::~QPointer() будет удален, когда объект MyClass выйдет из области видимости, и, следовательно, яудаляю m_process дважды?

Или я неправильно понял?

Ответы [ 2 ]

2 голосов
/ 04 мая 2019

Цель QPointer - предоставить защищенный или слабый указатель на подкласс QObject. Он не удаляет объект, когда выходит из области видимости, он просто знает, является ли объект, на который он указывает, живым или уже удален.

Таким образом, ваш текущий код верен в этом смысле. Несколько комментариев:

  • Бесполезно иметь значение по умолчанию nullptr для указателя в объявлении переменной, потому что вы инициализировали его в списке инициализатора конструктора.
  • Вам не нужно проверять, является ли указатель нулевым, перед удалением, потому что delete nullptr; является допустимым кодом, который ничего не делает.
  • Если время жизни вашего QProcess совпадает с временем жизни содержащего его объекта, то вы должны просто поместить его в качестве переменной-члена и вообще не использовать new, если только у вас нет какой-либо конкретной причины.
  • Если вы хотите использовать new для его выделения, подумайте, может ли QProcess иметь родителя QObject, который удалит его.
  • В качестве альтернативы, вы должны заключить указатель в QScopedPointer или std::unique_ptr, потому что они владеют объектом, на который они указывают, и будут удалять его, когда они выходят из области видимости.
1 голос
/ 04 мая 2019

QPointer не является умным указателем.Он не управляет объектом, на который он указывает.Он просто отслеживает, был ли он удален.Вам нужно будет удалить его самостоятельно:

~MyClass()
{
    delete m_process.data();
}

Когда вы удаляете указанный объект, data() будет иметь значение null.

Вам не нужно проверять, является ли оно нулевым, прежде чемудаляя его, потому что удаление нулевого указателя - это нормально (он просто ничего не делает.)

Я не думаю, что вам здесь нужен QPointer.Как сказано выше, этот класс полезен только для отслеживания того, был ли объект удален в другом месте.Вы, вероятно, не должны использовать указатель здесь вообще.Просто сделайте:

#include <QProcess>

class MyClass: public QObject {
private:
    QProcess m_process;
// ...

и измените код подключения на:

connect(&m_process, &QProcess::errorOccurred, this, [](QProcess::ProcessError error)
{
    qDebug() << "error: " << error;
});
...