Pregunta

A continuación, mi declaración de señal:

signals:
    void mySignal(MyClass *);

Y cómo lo estoy usando:

MyClass *myObject=new myClass();
emit mySignal(myObject);

Aquí viene mi problema: ¿Quién es responsable de la eliminación de myObject:

  1. Código del remitente, lo que si se elimina antes de myObject se utiliza? Colgando puntero

  2. La ranura conectada a la señal, lo que si no hay ninguna ranura o más de una ranura que está conectado a la señal? Pérdida de memoria o colgantes puntero

¿Cómo gestiona Qt esta situación en su acumulación en las señales? ¿Utiliza el recuento de referencia interna?

¿Cuáles son sus mejores prácticas?

¿Fue útil?

Solución

Se puede conectar una señal con el mayor número de ranuras, como se desea por lo que debe asegurarse de que ninguna de estas ranuras son capaces de hacer algo que no quiere que hagan con su objeto:

  • si decide pasar un puntero como un parámetro a continuación, va a correr en las cuestiones que usted describe, gestión de memoria - que aquí nadie puede con el trabajo para usted como usted tendrá que establecer una política para hacer frente a la asignación / eliminación. Para algunas ideas sobre cómo hacer frente a esta ver las Normas de Gestión de memoria en el COM mundo.
  • si decide pasar un parámetro de referencia, entonces no tiene que preocuparse de la gestión de memoria, pero sólo alrededor de ranuras La modificación de su objeto de manera inesperada. La idea pra no está a pasar punteros a menos que tenga a -. En lugar de utilizar referencias si es posible
  • si decide pasar una referencia const a continuación, dependiendo del tipo de conexión, QT pasará el valor del objeto para usted (ver este para algunos detalles)
  • evitar cualquier problema y pasar por valor:)

para algunos pensamientos acerca de pasar punteros en las señales.

Otros consejos

En su primera pregunta, el uso QPointer

En su segunda pregunta,

Si he entendido claramente, incluso si va a enviar myObject, que todavía tiene la referencia myObject en la clase en la que está emitiendo la señal. Entonces, ¿cómo va a ser una pérdida de memoria o una referencia colgante? Todavía se puede Acceso el myObject de la clase emitida, no lo es?

La esperanza me queda claro ..

Editar:

A partir de sus comentarios creo que están liberando / eliminación de los objetos en las ranuras. Ahora supongo que su problema es, ¿y si la ranura (memoria de la liberación) se llama una vez, dos veces o no se llama en absoluto.

Se puede utilizar QPointer para eso. A partir de la documentación de Qt,

punteros vigilado (QPointer) son útiles siempre que lo necesite para almacenar un puntero a una QObject que es propiedad de otra persona, y por lo tanto sea destruido, mientras que todavía mantiene una referencia a él. Puede probar con seguridad el puntero para la validez.

Un ejemplo de la documentación de Qt sí mismo,

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

la explicación sigue así ..

Si el QLabel se elimina, mientras tanto, la variable de etiqueta se mantenga 0 en lugar de una dirección no válida y no se ejecutará la última línea. Aquí QLabel será su MyClass y la etiqueta es su myObject. Y antes de utilizarlo para comprobar Nulidad .

A 1): El remitente debe tener cuidado. Cuando se envía la señal de forma sincrónica (en lugar de cola), el objeto está todavía vivo cuando un receptor recibe. Si las necesidades del receptor para almacenar, sólo un QPointer ayudaría, pero luego MyClass tiene que derivar de QObject, que se ve mal a partir del contexto. De todos modos, es decir un problema de tiempo de vida en general, no muy señal / slot-específico.

Alternativas: El uso de una clase de valor y enviarlo por referencia constante. Si MiClase puede tener subclases, pasar una const QSharedPointer y

Sobre deleteLater: deleteLater () no ayuda aquí. Haría conexiones en cola más seguro, y para las conexiones directas que no hace ninguna diferencia. El único uso, donde deleteLater () entra en juego es si el receptor tiene que eliminar el remitente. A continuación, uno siempre debe usar deleteLater (), por lo que el remitente puede completar lo que estaba haciendo, que de otro modo estrellarse.

En una palabra (bien, nombre de la función) - deleteLater () :) Todos QObjects lo tienen. Se marcará el objeto para su eliminación, y esto va a suceder a continuación, en la siguiente actualización de bucle de eventos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top