gpt4 book ai didi

c++ - Q_INVOKABLE const getter 返回 undefined,non-const getter 返回正确值 - 为什么?

转载 作者:行者123 更新时间:2023-12-02 10:04:12 25 4
gpt4 key购买 nike

我有简单的 c++ 类方法:

Q_INVOKABLE const QString& getRiderTypeName(const int& riderTypeIndex) const;

及其实现:
const QString& CumulativeSalesZoneModel::getRiderTypeName(const int& raiderTypeIndex) const   
{
static QString result=QString();

if(this->cumulativeSalesZoneData!=Q_NULLPTR)
{
result=this->cumulativeSalesZoneData->keys().at(raiderTypeIndex);
} // if

return result;
} // getRiderTypeName

以及何时从 QML 调用,它返回未定义的值。但是,如果我减少 const运算符,删除 reference并删除 static result 的声明作为返回值的一部分:
Q_INVOKABLE QString getRiderTypeName(const int& riderTypeIndex) const;

及其实现:
QString CumulativeSalesZoneModel::getRiderTypeName(const int& raiderTypeIndex) const
{
QString result=QString();

if(this->cumulativeSalesZoneData!=Q_NULLPTR)
{
result=this->cumulativeSalesZoneData->keys().at(raiderTypeIndex);
} // if

return result;
} // getRiderTypeName

我得到正确的值。为什么会这样?我在几个 Qt 上试过这个 Windows 上的版本, Linux和几个嵌入式板( Raspeberry PiToradex Colibri iMX6 和其他几个)。在@Azeem 请求下,我添加了相关的 QML代码:
Component.onCompleted:
{
riderTypeName=cumulativeSalesZoneModel.getRiderTypeName(riderTypesIndex);
console.log(riderTypeName);
} // Component.onCompleted

控制台输出:
qml: undefined

如果调用了第一个版本的方法,并且如果调用了第二个版本的方法,它会输出正确的值。

最佳答案

Revision # 1 (作为常量引用返回的非静态/本地数据):

const QString& CumulativeSalesZoneModel::getRiderTypeName( /*...*/ )
{
QString result = QString(); // non-static/local object
// ...
return result;
}

答案#1:

在 C++ 端,您试图返回局部变量的地址(引用),即 result .当代码块完成执行时,它将超出范围。所以,你最终得到一个悬空的引用。使用悬空引用将导致 Undefined Behavior .

检查你的编译日志。你一定会收到这样的警告:

warning: reference to stack memory associated with local variable 'result' returned



这是一个重现此警告的示例程序: https://godbolt.org/z/pZBq7H

注意 :一旦代码位于 Qt MOC/QML 端,以下关于返回引用的部分也适用于上面的答案 #1。

Revision # 2 (静态数据作为常量引用返回):
const QString& CumulativeSalesZoneModel::getRiderTypeName( /*...*/ )
{
static QString result = QString(); // static
// ...
return result;
}

根据 Qt Meta Object Compiler页面,它指出(强调我的):

Signals and slots can have return types, but signals or slots returning references will be treated as returning void.



而且,为了验证这一点,我创建了这个小的 test project与多个公众 Q_INVOKABLE方法。 QML 非常简单。返回的字符串显示为 title的 window 。

您需要观察 MOC 生成的文件。

生成的 moc_test.cpp包含这部分:
static const uint qt_meta_data_Test[] = {

// ... code removed for conciseness ...

// methods: name, argc, parameters, tag, flags
1, 0, 39, 2, 0x02 /* Public */,
3, 0, 40, 2, 0x02 /* Public */,
4, 0, 41, 2, 0x02 /* Public */,
5, 0, 42, 2, 0x02 /* Public */,
6, 0, 43, 2, 0x02 /* Public */,

// methods: parameters
QMetaType::QString,
QMetaType::QString,
QMetaType::QString,
QMetaType::Void,
QMetaType::Void,

0 // eod
};

正如您在上面的代码片段中观察到的(遵循“方法”注释),有 5 种方法。在最后一部分中,只有前 3 个具有返回类型,即 QString但最后 2 个返回 void .

并且,观察以下生成的方法:
void Test::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
auto *_t = static_cast<Test *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: { QString _r = _t->get1_RetByValue_NonConstLocalString();
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = std::move(_r); } break;
case 1: { QString _r = _t->get2_RetByConstValue_ConstLocalString();
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = std::move(_r); } break;
case 2: { QString _r = _t->get3_RetByConstValue_StaticString();
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = std::move(_r); } break;
case 3: _t->get4_RetByConstRef_LocalString(); break;
case 4: _t->get5_RetByStaticConstRef_StaticString(); break;
default: ;
}
}
}
switch 中的前 3 个案例正确设置参数数组,即 _a但最后2个案例没有。

这里要注意的有趣的事情是前 3 个有效案例中的代码,除了函数调用之外它是相同的,例如:
QString _r = _t->get<...>();    // first 3 variations of get method
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = std::move(_r);

返回 QString分配给 _r然后它被移动分配给 _a[0]来自 _r .

你可以得到 project并运行调试 session 以自己观察此行为。我希望这有帮助。

关于c++ - Q_INVOKABLE const getter 返回 undefined,non-const getter 返回正确值 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61038922/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com