c++ - 创建 QGenericArgument

标签 c++ qt

具有用于测试QMetaObject::invokeMethod 目的的简单应用程序:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setText( int value)
{
    QString s = QString::number(value);
    ui->textEdit->setText(s);
}





void MainWindow::on_pushButton_clicked()
{
    QGenericArgument genericArg =  Q_ARG(int, 321);
    bool inv = QMetaObject::invokeMethod( this,"setText",Qt::QueuedConnection, genericArg);
    qDebug("inv = %d\n", inv);
}

我在 setText 值中得到 0321 哪里去了?

最佳答案

让我们来看看引擎盖下发生了什么。

似乎整数 321 被视为 (const) ref https://doc.qt.io/qt-5/qmetaobject.html#Q_ARG :

QGenericArgument Q_ARG(Type, Type &value)
QGenericArgument Q_ARG(Type, const Type &value)

Q_ARG 只是一个宏:

#define Q_ARG(type, data) QArgument<type >(#type, data)

.. 返回类 QArugment 的对象:

template <class T>
class QArgument: public QGenericArgument
{
public:
    inline QArgument(const char *aName, const T &aData)
        : QGenericArgument(aName, static_cast<const void *>(&aData))
        {}
};

... 又基于QGenericArgument:

class Q_CORE_EXPORT QGenericArgument
{
public:
    inline QGenericArgument(const char *aName = Q_NULLPTR, const void *aData = Q_NULLPTR)
        : _data(aData), _name(aName) {}
    inline void *data() const { return const_cast<void *>(_data); }
    inline const char *name() const { return _name; }

private:
    const void *_data;
    const char *_name;
};

整个链只包含指向数据的 const 指针,因此可以肯定的是,问题在于对临时对象的悬空引用。

由于数据 321 只是一个临时数据,因此当 Q_ARG 被解析为构造函数时,它首先绑定(bind)到一个 const 引用,这样就可以了。

但是,根据cppreference标准的解释:https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary问题似乎是由于:

Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions:

(...)

a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696)

如果我的解释是正确的(不确定 pointer == reference 在这种情况下),那么程序处于快乐的未定义行为状态(Qt 需要取消引用悬空指针/ref运行 invokeMethod)。

因为它没有崩溃并使用 0 值(你怎么知道它被调用了?你调试过它了吗?)可能是你的构建配置隐藏了问题。

关于c++ - 创建 QGenericArgument,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50486892/

相关文章:

c++ - 引用继承自派生类的QList

c++ - 如何将 C++ 预处理器应用于 Ubuntu 上的 C++ 头文件

c++ - 与 extern "C"函数的友元似乎需要::来限定名称

c++ - std::shared_ptr 在按引用传递时如何跨类层次结构转换?

c++ - 如何在QT上显示处理结果?

c++ - 如何将 boost 库链接到我的项目?

python - 如何保持多个 QAbstractItemModel 类同步

python - 如何使用 operator [] 扩展 python 中的 c++ 类,使用 swig

c++ - 找出所有会导致此代码无限循环的 3 个错误

c++ - 这安全吗? (qt QQueue.dequeue() c++ 内联指针取消引用)