QMetaObject::invokeMethod传参异常:传入321却得到0
这个坑我之前踩过!你遇到的问题核心是**Q_ARG生成的临时对象生命周期问题**,导致invokeMethod调用时无法正确读取到你传入的321,最终拿到了无效的0值。
为什么会出现这个问题?
先看你代码里的这段:
QGenericArgument genericArg = Q_ARG(int, 321); bool inv = QMetaObject::invokeMethod( this,"setText",Qt::QueuedConnection, genericArg );
Q_ARG(Type, value)的本质是创建一个临时的QGenericArgument对象,它内部保存了一个指向传入value的指针。当你把Q_ARG(int,321)的结果赋值给genericArg变量时,这里的321是一个临时的int值——这条语句执行完后,这个临时int就会被销毁,genericArg里的指针也就指向了一块无效的内存。等到Qt的事件队列处理invokeMethod的调用时,读取到的就是这块无效内存里的随机值(刚好是0)。
怎么解决?
有两种简单的修复方式:
方式1:直接在invokeMethod中传入Q_ARG的结果
跳过中间变量,直接把Q_ARG(int,321)作为参数传给invokeMethod,这样临时值的生命周期会覆盖整个函数调用过程:
void MainWindow::on_pushButton_clicked() { bool inv = QMetaObject::invokeMethod( this, "setText", Qt::QueuedConnection, Q_ARG(int, 321) ); qDebug("inv = %d\n", inv); }
方式2:让传入的值拥有足够长的生命周期
如果你一定要用变量保存QGenericArgument,需要确保传入的value在invokeMethod完成调用前不会被销毁。比如把321存到一个局部变量(或者成员变量)里:
void MainWindow::on_pushButton_clicked() { int inputValue = 321; // 局部变量,生命周期覆盖整个函数 QGenericArgument genericArg = Q_ARG(int, inputValue); bool inv = QMetaObject::invokeMethod( this,"setText",Qt::QueuedConnection, genericArg ); qDebug("inv = %d\n", inv); }
这样inputValue的生命周期会持续到函数结束,即使是Qt::QueuedConnection,事件队列处理时它依然存在,就能正确读取到321了。
额外验证
你可以试试把连接类型改成Qt::DirectConnection,这时候invokeMethod会立即调用setText,可能能拿到正确的值——但这只是巧合,临时值还没被销毁,不是正确的写法,还是推荐上面两种方式。
内容的提问来源于stack exchange,提问作者vico

