如何将带有可变参数的插槽连接到带有常量参数的信号

How to connect slot with mutable argument to signal with const argument

我需要将 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);

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

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

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

你可能不想那样做。

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

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


QByteArray 使用 隐式共享 Qt 机制避免深度复制。
https://doc.qt.io/qt-5/implicit-sharing.html

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