Редакция № 1 (нестатические / локальные данные, возвращаемые в виде константной ссылки):
const QString& CumulativeSalesZoneModel::getRiderTypeName( /*...*/ )
{
QString result = QString(); // non-static/local object
// ...
return result;
}
Ответ № 1:
На стороне C ++ вы пытаетесь вернуть адрес (ссылку) локальной переменной, т.е. result
. К тому времени, когда блок кода завершит свое выполнение, go выйдет из области видимости. Итак, вы в конечном итоге с висящей ссылкой. Использование висячей ссылки приведет к неопределенному поведению .
Проверьте ваши журналы компиляции. Вы должны получить следующее предупреждение:
предупреждение: возвращена ссылка на стековую память, связанную с локальной переменной 'result'
Вот пример программы, воспроизводящей это предупреждение: https://godbolt.org/z/pZBq7H
ПРИМЕЧАНИЕ : Следующая часть, касающаяся возврата ссылок, также применяется к ответу № 1 выше, когда код находится в Qt MO C / Сторона QML.
Редакция # 2 (stati c данные возвращаются в виде констант-ссылки):
const QString& CumulativeSalesZoneModel::getRiderTypeName( /*...*/ )
{
static QString result = QString(); // static
// ...
return result;
}
Согласно Qt Мета-объектный компилятор страница, где говорится (выделено мое):
Сигналы и слоты могут иметь возвращаемые типы, но сигналы или слоты, возвращающие ссылки, будут рассматриваться как возвращающие void.
И, чтобы убедиться в этом, я создал этот небольшой test
проект с несколькими опубликованными c Q_INVOKABLE методами , QML довольно прост. Возвращаемая строка отображается в виде title
окна.
Вам необходимо просмотреть файлы, сгенерированные MO C.
Сгенерированный 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: ;
}
}
}
Первый 3 случая в switch
правильно устанавливают массив аргументов, т.е. _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
.
Вы можете получить проект и запустить сеанс отладки, чтобы самостоятельно наблюдать за этим поведением. Надеюсь, это поможет.