web-dev-qa-db-ja.com

Qtのメモリ管理?

私はQtを初めて使い、メモリ管理とオブジェクトの寿命に関する基本的なことを考えています。オブジェクトをいつ削除または破壊する必要がありますか?これは自動的に処理されますか?

以下の例では、作成するオブジェクトのうちどれを削除する必要がありますか? myOtherClassが破棄されると、インスタンス変数myClassはどうなりますか?オブジェクトをまったく削除(または破棄)しないとどうなりますか?それはメモリの問題でしょうか?

MyClass.h

class MyClass
{

public:
    MyClass();
    ~MyClass();
    MyOtherClass *myOtherClass;
};

MyClass.cpp

MyClass::MyClass() {
    myOtherClass = new MyOtherClass();

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}

ご覧のとおり、これは初心者向けの簡単なものですが、どこで簡単に学ぶことができますか?

90
Martin

QObjectsを使用して独自の階層を構築する場合、つまり、新しく作成されたすべてのQObjectsを親で初期化する場合、

_QObject* parent = new QObject();
QObject* child = new QObject(parent);
_

deletesデストラクタがparentの破棄を処理するため、parentchildで十分です。 (シグナルを発行することでこれを行うため、親の前で手動でchildを削除しても安全です。)

最初に子を削除することもできますが、順序は関係ありません。順序doesが重要な例については、ここでは オブジェクトツリーに関するドキュメント です。

MyClassQObjectの子ではない場合、単純なC++の方法を使用する必要があります。

また、QObjectsの親子階層は通常、C++クラス階層/継承ツリーの階層から独立していることに注意してください。つまり、割り当てられた子は、その親の直接のサブクラスである必要はありません。任意の(サブクラスの)QObjectで十分です。

ただし、他の理由でコンストラクターによって制約が課される場合があります。 QWidget(QWidget* parent=0)など。親が別のQWidgetである必要があります。可視性フラグ。基本的なレイアウトをそのように行うためです。しかし、一般的なQtの階層システムでは、QObjectを親として持つことができます。

95
Debilski

Qtでは所有権の概念が非常に重要であると指摘して、Debilskiの答えを拡張したいと思います。クラスAがクラスBの所有権を引き継ぐ場合、クラスAが削除されるとクラスBも削除されます。オブジェクトを作成してその親を指定するときだけでなく、あるオブジェクトが別のオブジェクトの所有者になる状況がいくつかあります。

例えば:

QVBoxLayout* layout = new QVBoxLayout;
QPushButton someButton = new QPushButton; // No owner specified.
layout->addWidget(someButton); // someButton still has no owner.
QWidget* widget = new QWidget;
widget->setLayout(layout); // someButton is "re-parented".
                           // widget now owns someButton.

もう一つの例:

QMainWindow* window = new QMainWindow;
QWidget* widget = new QWidget; //widget has no owner
window->setCentralWidget(widget); //widget is now owned by window.

したがって、ドキュメントを頻繁に確認してください。通常、メソッドがオブジェクトの所有権に影響するかどうかを指定します。

Debilskiが述べたように、これらのルールはQObjectから派生したオブジェクトにのみ適用されます。クラスがQObjectから派生していない場合、破壊を自分で処理する必要があります。

46
Austin

親(QObjectオブジェクトまたはその派生クラス)には、その子(QObject /その派生)へのポインターのリストがあります。親は破棄されますが、親は子リスト内のすべてのオブジェクトを削除します。 QObjectのこのプロパティを使用して、親が削除されるたびに子オブジェクトを自動的に削除することができます。次のコードを使用して関係を確立できます

QObject* parent = new QObject();
QObject* child = new QObject(parent);
delete parent;//all the child objects will get deleted when parent is deleted, child object which are deleted before the parent object is removed from the parent's child list so those destructor will not get called once again.

Smartpointerを使用して、Qtでメモリを管理する他の方法があります。次の記事では、Qtのさまざまなスマートポインターについて説明します。 https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/

7
yesraaj