Qt事件数据析构函数

Qt event data destructor

假设有一个带信号的qt对象。该对象发出一个信号,其中包含分配在堆上的一些对象 (new/malloc)。事件的析构函数释放所有分配的数据。如果没有连接到 qt-object 信号,这些数据会以任何方式释放吗?如果侦听器在其信号槽中接收到事件之前关闭连接?

添加:

带有缩短的示例。

  class MyEvent { virtual ~MyEvent(); }; // root class for all my project events
  class MyEventQueue {
      MyEventQueue();                // initialize mutex
      virtual ~MyEventQueue();       // delete and release all events from events_
      void push_back( MyEvent *);    // atomic-push event
      MyEvent *pop_front();          // atomic-pop  event
      pthread_mutex_t sync_;         // mutex for atomic operations
      std::queue<MyEvent *> events_; // queue of events
  };
  class MyEvent1 : public MyEvent {
      MyEvent1( char *);
      ~MyEvent1() { delete[] data; }
      char *data;
  };
  class MyWriter {
      ...;
      void eval();
      signals: void send1( MyEventQueue *);
      MyEventQueue queue_;
  };
  class MyReader {
      ...;
      slots: void recv1( MyEventQueue *);
  };
  class MyController {
      ...;
  }

MyWriter 和 MyReader 是在一个进程的不同线程中工作的独立参与者。

void MyWriter::eval() {
    ...;
    queue_.push_back( new MyEvent1( ...));
    emit send1( &queue_);
}

void MyReader::recv1( MyEventQueue *queue) {
    if ( MyEvent *event = queue->pop_front() ) {
        // event is delivered to MyReader
        ...;
        delete event;
    }
}

如果发送的事件已送达并被接受,它将在 MyReader 中删除。以其他方式,事件将保存在 MyWriter::queue_.

MyController 作为 MyWriter 和 MyReader 的 dispatcher/manager。它还实现了与其他功能块的通信。在(外部)数据处理周期结束时,MyController 停止 MyWriter、MyReader(它们的线程以及它们的 qt 事件循环)。然后它关闭 MyWriter 和 MyReader 之间的连接。如果某些事件由 MyWriter 发送,但未被 MyReader 接受,则分配的数据将在 ~MyWriter() -> queue_ 的析构函数中释放。

(对于多个读者,我在 MyController 中使用显式重新发送事件处理或仅一对一连接,在这种情况下,MyController 用作具有自身事件队列的路由器。)

主要原因是数据处理的流水线化和并行化。

我怀疑我是否重复了 qt-engine 的工作。当然,也许还有更好的解决办法。

关于向信号传递参数的一般建议

是否销毁作为信号参数传递的对象取决于您。请注意,多个插槽可能会连接到同一个信号,这可能会导致多次破坏对象。

一些(常见的)可能性是:

  • 通过 const 引用传递。当使用 queued connection 时,Qt 将创建一个副本。否则将不会复制。
  • 按值传递。对基本类型有用,否则通过 const 引用传递。
  • 传递共享指针。

另一个选项可能是使用 QObject::isSignalConnected 检查插槽是否连接到信号。如果参数需要大量资源来构建,此函数对于避免信号发射特别有用。但是,我不建议您使用此选项,因为它不能解决多个插槽连接到同一信号的情况。

另一种可能性是实现您自己的回调方法,这将允许您强制执行唯一的回调方法。