2

Qtでは、独自のQWidgetをセットアップしようとしているので、メモリ管理などの理由ですべてが正常に機能するはずです。しかし、ポインター、ヒープ、スタックではうまくいかないようです。いくつかのオブジェクトを含むQListを持つウィジェットMyWidgetがあります。すべてを正しく設定する方法がわかりません。

あなたは私のコードを以下に見ることができます、そして私はこれに関していくつかの質問があります:

  1. instace変数リストはヒープ上に作成されますが、スタック上に作成する方がよいでしょうか?

  2. 私のリストにはポインタがありますが、スタック上にオブジェクトを作成してリストに追加する方がよいでしょうか?(リストにポインタがまったくないようにするため)

  3. オブジェクトをリストに追加すると、オブジェクトは自動的に親としてリストを取得しますか?リストを削除すると、リスト内のすべてのオブジェクトが削除されますか?

  4. 使用しようとしているforeachループが機能していません。「この操作では、「int」ではなく、ポインター/配列型が必要でした」というメッセージが表示されました。

  5. 私のコードでは、リストからオブジェクトをパラメーターとして受け取る他のウィジェットを作成したいと思います。私のようにそれを行う正しい方法ですか?MyOtherWidgetのインスタンスメソッドは次のようになります。MyOtherWidget(MyObject * myObject、QWidget * parent)

ご協力いただきありがとうございます!私はQtとC++を初めて使用するので、正しい方向に導いていただければ幸いです。簡単に、メモリリークが発生せず、必要なだけメモリを使用しないように、これを正しい方法で設定するにはどうすればよいですか。同じことをどのように設定しますか?

これは私のコードです:

MyWidget.h:

class MyWidget : public QWidget
{
Q_OBJECT

public:
    MyWidget(QWidget *parent = 0);
    ~MyWidget();

private:
    QList<MyObject*> *list;
};

MyWidget.cpp:

MyWidget::MyWidget(QWidget *parent)
{
    ui.setupUi(this);

    list = new QList<MyObject*>();
    for (int i = 0; i<10; i++) 
    {
        MyObject *myObject = new MyObject("Hello",this);
        list->append(myObject);
    }

    foreach(MyObject *myObject, list)
    {
        //Lets say I want to create other widgets here and that they takes a MyObject as a parameter
        MyOtherWidget *myOtherWidget = new MyOtherWidget(myObject,this);
    }

}

MyWidget::~MyWidget(){
    delete list;
}
4

3 に答える 3

1

Ad.1。リストの有効期間は、MyWidgetインスタンスの有効期間と同じである必要があります。これにより、スタック上にリストを安全に作成できます。

Ad.2。それは可能ですが、MyObjectクラスには、デフォルトコンストラクター、コピーコンストラクター、および代入演算子が必要です(詳細については、http://doc.trolltech.com/4.6/containers.html#container-classesを参照してください)。

Ad.3。オブジェクトの所有権は、追加時に譲渡されません。STLコンテナと同様に、Qtコンテナは保存されたポインタに対してdeleteを呼び出しません。QList(または他のQtコンテナー)に保管されているすべてのポインターを削除するには、qDeleteAll(list)を使用できます。投稿したコードではおそらくそうしたくないことに注意してください。MyWidgetポインターをMyObjectコンストラクターに渡し、それがQObjectの親として使用されると思います。したがって、MyWidgetが削除されると、すべてのQObjectが削除されます。

Ad.4。foreachマクロの2番目の引数は、コンテナーへのポインターではなく、コンテナーである必要があります。したがって、リスト変数がQListへのポインターである場合は、foreach(MyObject * obj、* list)を呼び出す必要があります。

Ad.5。MyOtherWidgetが渡されたMyObjectを削除しない限り、問題はありません(MyWidgetはすでにMyObjectの親であり、同じオブジェクトを2回削除することになります)。

これは非常に単純化されていますが、deleteを呼び出す必要がまったくないような方法でコードを記述してみてください。スタック上にものを作成するか、Qtの親子メカニズムに依存します(つまり、親が子を削除します)。後で、スマートポインター(QSharedPointer、QScopedPointerなど)について読みたいと思うかもしれません。

編集:

MyObjectの親が設定されているかどうかは、MyObjectコンストラクターで何をしているかによって異なります。親引数をQObjectコンストラクターに渡す場合、つまりMyobjectコンストラクターは次のようになります。

MyObject(const QString &text, QObject *parent = 0) : QObject(parent)
{
// more code...
}

親が設定されます。これは、「:QObject(parent)」コードのために呼び出されるQObjectコンストラクターで行われるためです。このフラグメントがない場合はどうなりますか?MyObjectはQObjectを継承し、デフォルトのQObjectコンストラクターと呼ばれるコンストラクターを指定しないため、QObject(QObject * parent = 0)が呼び出されるため、MyObjectの親はNULLになり、呼び出されません。削除されました。

setParentメソッドを使用して親を明示的に設定することは避けたいと思います。基本的なユースケースでは、コンストラクターで親を設定するだけで十分です。

正しい用語(「インスタンスメソッド」ではなく「コンストラクター」)を使用し、Qtのドキュメントを読み、常識を使用して、何かが自動的に行われるとは思わないようにしてください。1つの引数を「親」と呼んだからといって、親が「自動的に」設定されるわけではありません。QObjectコンストラクターでそれを行うコードがあり、クラス内のQObjectコンストラクターに適切な親を渡すのはユーザーの責任であるためです。 QObjectを継承します。

于 2010-03-29T13:55:45.217 に答える
0

はい、問題は、リストのオブジェクトを削除しているが、その要素は削除していないことです。

私はあなたが見てみることをお勧めします:

QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));

qDeleteAll(list.begin(), list.end());
list.clear();

詳細はこちら

また、リストへのポインタが本当に必要かどうかも尋ねます。あなたは単純なものを持つことができます:

QList<MyObject*> list;

したがって、メモリリークの可能性が1つ少なくなります。

これが少し役立つことを願っています!

編集:
3。MyObjectオブジェクトには親として「this」があります。ポインタを扱う場合、リストはオブジェクトの所有権を取得しません。
4.ループについては、イテレータを検討する必要があります。qthelp://com.trolltech.qt.460/qdoc/qlist.htmlを参照してください。

于 2010-03-29T13:34:23.400 に答える
0

子ウィジェットを現在のウィジェットの親にする限り、子ウィジェットをリスト内に格納する必要はありません。(通常、新しいウィジェットをスタックに作成します)。

Qtには自動クリーンアップ機能があります。つまり、ウィジェットが削除されると、すべての子ウィジェット(親が削除されるウィジェットであるウィジェット)が削除されます。

したがって、(特に一時的なポップアップウィジェットの場合)ウィジェットの「ポップアップ」を消去/削除するか、ポップアップウィジェットを呼び出すかを確認する必要がある唯一のことです。

それだけです、それだけです。

于 2010-03-29T20:28:09.617 に答える