Q_可调用常量getter返回未定义的值,非常量getter返回正确的值-为什么? 我有简单的C++类方法: Q_INVOKABLE const QString& getRiderTypeName(const int& riderTypeIndex) const;

Q_可调用常量getter返回未定义的值,非常量getter返回正确的值-为什么? 我有简单的C++类方法: Q_INVOKABLE const QString& getRiderTypeName(const int& riderTypeIndex) const;,c++,qt,qml,C++,Qt,Qml,在实施过程中: const QString& CumulativeSalesZoneModel::getRiderTypeName(const int& raiderTypeIndex) const { static QString result=QString(); if(this->cumulativeSalesZoneData!=Q_NULLPTR) { result=this->cumulativeSalesZo

在实施过程中:

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
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
当从调用时,它返回未定义的值。但是,如果我使用reduce运算符,则删除a并删除
result
的声明,作为返回值的一部分:

Q_INVOKABLE 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
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
我得到了正确的值。为什么会这样?我已经在
Windows
Linux
和几个嵌入式板(,以及其他几个)上尝试过这个版本。根据@Azeem请求,我正在添加相关的
QML
code:

Component.onCompleted:
{
    riderTypeName=cumulativeSalesZoneModel.getRiderTypeName(riderTypesIndex);
    console.log(riderTypeName);
}   // Component.onCompleted
控制台输出:

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

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

回答#1:

在C++侧,您试图返回本地变量的地址(引用),即“代码>结果< /代码>。当代码块完成执行时,它将超出范围。所以,你最终得到了一个悬而未决的参考。使用悬空引用将导致错误

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

警告:返回了对与局部变量“result”关联的堆栈内存的引用

下面是一个复制此警告的示例程序:


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

(作为常量引用返回的静态数据):

根据Qt页面,它指出(我的重点):

信号和插槽可以有返回类型,但返回引用的信号或插槽将被视为返回无效。

为了验证这一点,我用多种公共方法创建了这个小程序。QML非常简单。返回的字符串显示为窗口的
标题

您需要观察MOC生成的文件

生成的
moc_测试.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: ;
        }
    }
}
返回的
QString
分配给
\u r
,然后从
\u r
移动分配给
\u a[0]



您可以获取并运行调试会话以自己观察此行为。我希望这有帮助。

@ AZZEM是真的,我已经提出了这个问题,但是问题的焦点不是C++侧,而是为什么我在QML边得到了未定义的值。@ Keln惊慌:因为它是定义的实现的未定义行为。你可能得到垃圾值或者没有-任何东西都是可能的。@ Azzem上的C++已经不再是这样了,我已经纠正了它,就像我在以前的帖子里说过的。KernelPanic:你问的是,当你从返回值中删除const REF时会发生什么?是吗?我看不出这不是一个公认的答案。接受的答案与OP中的问题无关
QString _r = _t->get<...>();    // first 3 variations of get method
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = std::move(_r);