c++ - guia - Manejo de memoria en Qt?
qgis manual (3)
Me gustaría extender la respuesta de Debilski señalando que el concepto de propiedad es muy importante en Qt. Cuando la clase A asume la propiedad de la clase B, la clase B se elimina cuando se elimina la clase A. Hay varias situaciones en las que un objeto se convierte en el propietario de otro, no solo cuando crea un objeto y especifica su elemento principal.
Por ejemplo:
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.
Otro ejemplo:
QMainWindow* window = new QMainWindow;
QWidget* widget = new QWidget; //widget has no owner
window->setCentralWidget(widget); //widget is now owned by window.
Por lo tanto, consulte la documentación con frecuencia, generalmente especifica si un método afectará la propiedad de un objeto.
Según lo establecido por Debilski, estas reglas se aplican ÚNICAMENTE a los objetos que se derivan de QObject. Si su clase no se deriva de QObject, tendrá que manejar la destrucción usted mismo.
Soy bastante nuevo en Qt y me estoy preguntando sobre algunas cosas básicas con la administración de la memoria y la vida de los objetos. ¿Cuándo debo eliminar y / o destruir mis objetos? ¿Se maneja algo de esto automáticamente?
En el siguiente ejemplo, ¿cuál de los objetos que creo necesito eliminar? ¿Qué sucede con la variable de instancia myOtherClass
cuando se destruye myClass
? ¿Qué sucede si no elimino (o destruyo) mis objetos? ¿Será eso un problema para la memoria?
MyClass.h
class MyClass
{
public:
MyClass();
~MyClass();
MyOtherClass *myOtherClass;
};
MyClass.cpp
MyClass::MyClass() {
myOtherClass = new MyOtherClass();
MyOtherClass myOtherClass2;
QString myString = "Hello";
}
Como puede ver, esto es bastante nuevo, cosas fáciles pero ¿dónde puedo aprender sobre esto de una manera fácil?
Parent (o objeto QObject o su clase derivada) tiene una lista de puntero a sus hijos (QObject / its derived). El padre eliminará todos los objetos en su lista secundaria mientras el padre se destruye. Puede utilizar esta propiedad de QObject para hacer que los objetos secundarios se eliminen automáticamente cuando se elimine el elemento primario. La relación se puede establecer usando el siguiente código
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.
Hay otra manera de administrar la memoria en Qt, utilizando smartpointer. El siguiente artículo describe varios indicadores inteligentes en Qt. https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/
Si construye su propia jerarquía con QObject
s, es decir, inicializa todos los QObject
s recién creados con un padre,
QObject* parent = new QObject();
QObject* child = new QObject(parent);
entonces es suficiente delete
el parent
, porque el destructor del parent
se encargará de destruir al child
. (Hace esto emitiendo señales, por lo que es seguro incluso cuando elimina child
manualmente antes que el elemento principal).
También puede eliminar al niño primero, el orden no importa. Para un ejemplo donde la orden realmente importa, aquí está la documentación sobre árboles de objetos .
Si su MyClass
no es un elemento secundario de QObject
, tendrá que usar la forma simple de C ++ de hacer las cosas.
Además, tenga en cuenta que la jerarquía principal-secundaria de QObject
s generalmente es independiente de la jerarquía del árbol de jerarquía / herencia de la clase C ++. Eso significa que un niño asignado no necesita ser una subclase directa de su padre . Cualquier (subclase de) QObject
será suficiente.
Sin embargo, puede haber algunas restricciones impuestas por los constructores por otras razones; como en QWidget(QWidget* parent=0)
, donde el padre debe ser otro QWidget
, debido, por ejemplo, a indicadores de visibilidad y porque harías un diseño básico de esa manera; pero para el sistema de jerarquía de Qt en general, se le permite tener cualquier QObject
como padre.