Qt,作为信号发送参考时的数据完整性

Qt,作为信号发送参考时的数据完整性,qt,signals-slots,qt-signals,Qt,Signals Slots,Qt Signals,如果我发送一个引用对象的信号,我是否有任何保证,在对象受到程序其他部分的更改之前,插槽将处理该信号 或者我必须发送一份带有信号的物体的深度副本才能确定吗 以下条件成立:信号返回时: 已调用所有直接连接的插槽 已调用所有阻塞排队连接的插槽 所有具有排队连接插槽的目标对象都向其发布了相关的QMetaCallEvent 因此,如果您的其他代码允许,并且连接是: 直接的 阻塞队列,或 与当前线程中的目标对象自动关联 对于这些连接类型,在signal方法返回之前将调用所有插槽。回想一下,信号是其他的普

如果我发送一个引用对象的信号,我是否有任何保证,在对象受到程序其他部分的更改之前,插槽将处理该信号


或者我必须发送一份带有信号的物体的深度副本才能确定吗

以下条件成立:信号返回时:

  • 已调用所有直接连接的插槽

  • 已调用所有阻塞排队连接的插槽

  • 所有具有排队连接插槽的目标对象都向其发布了相关的
    QMetaCallEvent

  • 因此,如果您的其他代码允许,并且连接是:

    • 直接的
    • 阻塞队列,或
    • 与当前线程中的目标对象自动关联
    对于这些连接类型,在signal方法返回之前将调用所有插槽。回想一下,信号是其他的普通C++方法,它们的实现是由MOC。 还记得自动连接类型在发出信号时被解析。如果目标对象位于当前线程中,则使用直接连接,否则将导致排队连接

    当然,所有这些保证都假定您的插槽都不会修改对象不要忘记,仅仅通过常量引用传递对象是不够的——毕竟,有些对象可能能够直接访问您的对象。代码的设计必须满足您所寻求的保证

    如果连接是:

    • 排队,或
    • 自动,目标对象位于当前线程以外的线程中
    通过引用将数据传递到直接连接的插槽不会复制实例:

    //main.cpp
    #include <QDebug>
    
    class Data {
       int m_i;
    public:
       Data(const Data & o) : m_i(o.m_i) {
          qDebug() << "copy constructed";
       }
       Data(int i = 0) : m_i(i) {
          qDebug() << "constructed";
       }
       Data(Data && o) : m_i(o.m_i) {
          qDebug() << "move constructed";
       }
       ~Data() {
          qDebug() << "destructed";
       }
       int i() const { return m_i; }
    };
    Q_DECLARE_METATYPE(Data)
    
    QDebug operator<<(QDebug dbg, const Data & d)
    {
       dbg << "Data:" << d.i();
       return dbg;
    }
    
    class Object : public QObject {
       Q_OBJECT
    public:
       Q_SIGNAL void source(const Data &);
       Q_SLOT void sink(const Data & d) {
          qDebug() << "sinking" << d;
       }
    };
    
    int main()
    {
       qDebug() << QT_VERSION_STR;
       Object o;
       o.connect(&o, SIGNAL(source(Data)), SLOT(sink(Data)));
       emit o.source(Data(2));
       return 0;
    }
    
    #include "main.moc"
    

    以下情况适用:信号返回时:

  • 已调用所有直接连接的插槽

  • 已调用所有阻塞排队连接的插槽

  • 所有具有排队连接插槽的目标对象都向其发布了相关的
    QMetaCallEvent

  • 因此,如果您的其他代码允许,并且连接是:

    • 直接的
    • 阻塞队列,或
    • 与当前线程中的目标对象自动关联
    对于这些连接类型,在signal方法返回之前将调用所有插槽。回想一下,信号是其他的普通C++方法,它们的实现是由MOC。 还记得自动连接类型在发出信号时被解析。如果目标对象位于当前线程中,则使用直接连接,否则将导致排队连接

    当然,所有这些保证都假定您的插槽都不会修改对象不要忘记,仅仅通过常量引用传递对象是不够的——毕竟,有些对象可能能够直接访问您的对象。代码的设计必须满足您所寻求的保证

    如果连接是:

    • 排队,或
    • 自动,目标对象位于当前线程以外的线程中
    通过引用将数据传递到直接连接的插槽不会复制实例:

    //main.cpp
    #include <QDebug>
    
    class Data {
       int m_i;
    public:
       Data(const Data & o) : m_i(o.m_i) {
          qDebug() << "copy constructed";
       }
       Data(int i = 0) : m_i(i) {
          qDebug() << "constructed";
       }
       Data(Data && o) : m_i(o.m_i) {
          qDebug() << "move constructed";
       }
       ~Data() {
          qDebug() << "destructed";
       }
       int i() const { return m_i; }
    };
    Q_DECLARE_METATYPE(Data)
    
    QDebug operator<<(QDebug dbg, const Data & d)
    {
       dbg << "Data:" << d.i();
       return dbg;
    }
    
    class Object : public QObject {
       Q_OBJECT
    public:
       Q_SIGNAL void source(const Data &);
       Q_SLOT void sink(const Data & d) {
          qDebug() << "sinking" << d;
       }
    };
    
    int main()
    {
       qDebug() << QT_VERSION_STR;
       Object o;
       o.connect(&o, SIGNAL(source(Data)), SLOT(sink(Data)));
       emit o.source(Data(2));
       return 0;
    }
    
    #include "main.moc"
    

    以下情况适用:信号返回时:

  • 已调用所有直接连接的插槽

  • 已调用所有阻塞排队连接的插槽

  • 所有具有排队连接插槽的目标对象都向其发布了相关的
    QMetaCallEvent

  • 因此,如果您的其他代码允许,并且连接是:

    • 直接的
    • 阻塞队列,或
    • 与当前线程中的目标对象自动关联
    对于这些连接类型,在signal方法返回之前将调用所有插槽。回想一下,信号是其他的普通C++方法,它们的实现是由MOC。 还记得自动连接类型在发出信号时被解析。如果目标对象位于当前线程中,则使用直接连接,否则将导致排队连接

    当然,所有这些保证都假定您的插槽都不会修改对象不要忘记,仅仅通过常量引用传递对象是不够的——毕竟,有些对象可能能够直接访问您的对象。代码的设计必须满足您所寻求的保证

    如果连接是:

    • 排队,或
    • 自动,目标对象位于当前线程以外的线程中
    通过引用将数据传递到直接连接的插槽不会复制实例:

    //main.cpp
    #include <QDebug>
    
    class Data {
       int m_i;
    public:
       Data(const Data & o) : m_i(o.m_i) {
          qDebug() << "copy constructed";
       }
       Data(int i = 0) : m_i(i) {
          qDebug() << "constructed";
       }
       Data(Data && o) : m_i(o.m_i) {
          qDebug() << "move constructed";
       }
       ~Data() {
          qDebug() << "destructed";
       }
       int i() const { return m_i; }
    };
    Q_DECLARE_METATYPE(Data)
    
    QDebug operator<<(QDebug dbg, const Data & d)
    {
       dbg << "Data:" << d.i();
       return dbg;
    }
    
    class Object : public QObject {
       Q_OBJECT
    public:
       Q_SIGNAL void source(const Data &);
       Q_SLOT void sink(const Data & d) {
          qDebug() << "sinking" << d;
       }
    };
    
    int main()
    {
       qDebug() << QT_VERSION_STR;
       Object o;
       o.connect(&o, SIGNAL(source(Data)), SLOT(sink(Data)));
       emit o.source(Data(2));
       return 0;
    }
    
    #include "main.moc"
    

    以下情况适用:信号返回时:

  • 已调用所有直接连接的插槽

  • 已调用所有阻塞排队连接的插槽

  • 所有具有排队连接插槽的目标对象都向其发布了相关的
    QMetaCallEvent

  • 因此,如果您的其他代码允许,并且连接是:

    • 直接的
    • 阻塞队列,或
    • 与当前线程中的目标对象自动关联
    对于这些连接类型,在signal方法返回之前将调用所有插槽。回想一下,信号是其他的普通C++方法,它们的实现是由MOC。 还记得自动连接类型在发出信号时被解析。如果目标对象在当前线程中,则使用直接连接,否则将导致排队连接