【问题标题】:How to connect slot with mutable argument to signal with const argument如何将带有可变参数的插槽连接到带有 const 参数的信号
【发布时间】:2021-11-14 10:19:20
【问题描述】:

我需要将 QWebSocket 的 binaryMessageReceived 信号连接到修改 QByteData 的插槽

QByteData 可能很大,因此每次在可变变量中再次复制它可能真的很昂贵。我想重用现有的 QByteData

当我尝试使用以下插槽进行编译时

void route(QByteArray& msg);

我得到编译错误

/usr/include/qt/QtCore/qobject.h:255:9: error: static assertion failed: Signal and slot arguments are not compatible.
  255 |         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
      |         ^~~~~~~~~~~~~~~~~
/usr/include/qt/QtCore/qobject.h:255:9: note: ‘(((int)QtPrivate::CheckCompatibleArguments<QtPrivate::List<const QByteArray&>, QtPrivate::List<QByteArray&> >::value) != 0)’ evaluates to false

但如果我将插槽更改为

void route(const QByteArray& msg);

它编译得很好

我正在像这样连接插槽:-

connect(this, &QWebSocket::binaryMessageReceived, this, &WSManager::route);

【问题讨论】:

    标签: c++ qt constants signals-slots


    【解决方案1】:

    我认为你可以连接到 lambda 并在 lambda 函数中使用 const_cast:

    connect(this, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray &message) {
        this->route(const_cast<QByteArray &>(message));
    });
    

    更新:即使您可以通过这种方式抛弃 constness,但这并不意味着这样做是个好主意:) 正如在另一个答案中指出的那样,由于 Qt 隐式共享机制,不会对未更改的 QByteArray 进行数据复制.

    【讨论】:

    • 鉴于QWebSocket 使用const 引用而不是可变引用调用它,我预计这样做非常不安全,这可能是未定义行为的来源。我们是否有任何正式保证可以安全地改变QByteArray(例如QWebSocket 不关心调用后的数据),并且通过插槽传递的QByteArray 对象实际上不是const另一方面?如果我们没有这些保证,那么这个const_cast 是不安全的。
    • 我同意@Human-Compiler。我只专注于“如何”,但没有指出它是否明智。用评论更新了我的答案,并支持了 ymoreau 的答案。
    【解决方案2】:

    你可能不想这样做。

    如果作为const &amp; 传递,信号参数不会被修改。您甚至不确定发射器对象 (QWebSocket) 中二进制数据的生命周期。

    QByteData 从这里发出:https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp.html#181
    嵌套在对 API 隐藏的多个类中,依赖这种属性/数据是非常危险的。


    QByteArray 使用 implicit-sharing Qt 机制,避免了深拷贝。
    https://doc.qt.io/qt-5/implicit-sharing.html

    这意味着您可以传递对象而不用担心性能。如果在某些时候您需要对其进行修改,由于移动操作符,您最终可能会处理数据的唯一实际实例。

    【讨论】:

      猜你喜欢
      • 2020-09-21
      • 1970-01-01
      • 2013-09-28
      • 2022-07-21
      • 1970-01-01
      • 2012-05-02
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多