2009-10-30 4 views
14

Ich war auf der Suche here:Qt: führt "neu ohne Löschen" zu Speicherlecks mit Steuerelementen? bei Qt Beispiel

und innerhalb des Konstruktors, sie haben:

Window::Window() 
{ 
    editor = new QTextEdit(); // Memory leak? 
    QPushButton *sendButton = new QPushButton(tr("&Send message")); // Memory leak? 

    connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage())); 

    QHBoxLayout *buttonLayout = new QHBoxLayout(); // Memory leak? 
    buttonLayout->addStretch(); 
    buttonLayout->addWidget(sendButton); 
    buttonLayout->addStretch(); 

    QVBoxLayout *layout = new QVBoxLayout(this); // Memory leak? 
    layout->addWidget(editor); 
    layout->addLayout(buttonLayout); 

    setWindowTitle(tr("Custom Type Sending")); 
} 

diese Zeilen mit Kommentaren

// Memory leak? 

sind nicht diejenigen Speicherlecks?

Wenn ja, da die Window-Klasse keinen Konstruktor hat, sollte ich alle diese Variablen machen (Editor ist bereits) Window-Member-Variablen?

Or..löscht Qt intern diese Membervariablen, wenn der Gültigkeitsbereich überschritten wird?

Antwort

25

Nein, die addWidget() Funktion behält die Eigentümerschaft des Widgets bei. Es wird dann die Widgets zerstören, die es besitzt.

Zusätzlich können Sie lesen here, die:

Wie bei QObjects kann QWidgets mit übergeordneten Objekten zu Eigentum hinweisen erstellt werden, um sicherzustellen, dass Objekte gelöscht werden, wenn sie keine mehr verwendet werden. Bei Widgets haben diese Eltern-Kind-Beziehungen eine zusätzliche Bedeutung: : Jedes untergeordnete Widget wird auf dem Bildschirm angezeigt, der vom übergeordneten Widget belegt ist. Das bedeutet, dass beim Löschen eines Fenster-Widgets alle darin enthaltenen untergeordneten Widgets ebenfalls gelöscht werden.

+0

+1 Ich vermutete in meiner gelöschten Antwort :) – AraK

7

Wenn eine Ausnahme zwischen new und addWidget geworfen wird, dann gibt es einen Speicherverlust. Andernfalls übernimmt das übergeordnete Steuerelement den Besitz des Speichers.

QHBoxLayout *buttonLayout = new QHBoxLayout(); // Memory leak? 
//make sure you don't throw here 
buttonLayout->addWidget(sendButton); 
5

Neben korrekte Antwort des Klaim:

ich diese Zeiger in einem std::auto_ptr speichern würde, Sie zu ihren Eltern geben sie mittlerweile.

std::auto_ptr<QHBoxLayout> buttonLayout(new QHBoxLayout()); 
// make things which could throw... 
layout->addLayout(buttonLayout.release()); 

Auf diese Weise sind Sie sicher, keine Lecks zu haben.

+0

Noch besser als meine eigene Antwort –

+0

Wird es nicht doppelt gelöscht, wenn Sie dies tun? Einmal von auto_ptr, dann wieder von QObject? – James

+2

Ersetze std :: auto_ptr durch std :: unique_ptr ... – Klaim

0

Es wird wegen des Aufrufs .release() nicht doppelt gelöscht.

Hinweis std :: unique_ptr ersetzt std :: auto_ptr. Hoffentlich unterstützt QT die move-Semantik, dann würde release() stattdessen layout-> addLayout (std :: move (buttonLayout)) sein und ohne den Aufruf zu verschieben, würden Sie einen Kompilierungsfehler bekommen.

+1

es ist shared_ptr das ersetzt auto_ptr, unique_ptr ist nur für bereichsgebundene ptrs nicht zum teilen, das sagte, es ist perfekt für diesen job, da wir es nicht teilen wollen. –