Qt 将右值引用传递给QVariant不适用于QString

Qt 将右值引用传递给QVariant不适用于QString,qt,rvalue-reference,qstring,qvariant,stdmove,Qt,Rvalue Reference,Qstring,Qvariant,Stdmove,我正在尝试将一个右值引用从一个函数返回到一个QVariant。 它适用于bool和int,但当我传递字符串时,会得到一个“无效”的QVariant 我的职能: QVariant &&AudioSettings::getValueFromTable(const QString &name) { QSqlQuery query(_messengerDB); auto queryStr = QString("SELECT %1 FROM user_audio W

我正在尝试将一个右值引用从一个函数返回到一个QVariant。 它适用于bool和int,但当我传递字符串时,会得到一个“无效”的QVariant

我的职能:

QVariant &&AudioSettings::getValueFromTable(const QString &name)
{
    QSqlQuery query(_messengerDB);
    auto queryStr = QString("SELECT %1 FROM user_audio WHERE id = 1;").arg(name);
    if(query.exec(queryStr)){

        if(query.next()){
            qDebug() << "AudioSettings::getValueFromTable" << query.value(0);  //here I have a correct QString value => QVariant(QString, "Głośniki (USB Audio CODEC )")
            return std::move(query.value(0));

        } else {
            qDebug() << "AudioSettings::setValueToTable : No data for '" << queryStr << "'";
            return QVariant();
        }

    } else {
        qDebug()<<"AudioSettings::setValueToTable : Error during getting " << name << " form table user_audio.";
        qDebug() << query.lastQuery();
        qDebug() << query.lastError();
    }
    return QVariant();
}
有效的方法是:

int AudioSettings::getRingtoneType()  //EDIT
{
    auto value = getValueFromTable("ringtone_type");  //EDIT, I am getting a QVariant with an int inside
    return value.isNull() ? 0 : value.toInt();
}

有人知道原因吗?

如评论中所述,您正在返回一个悬而未决的引用。所以你有未定义的行为,任何事情都可能发生

在这种情况下,QVariant保存一个整数。我的猜测是,您很幸运,保存int的内存没有被重写(或释放)

对于运气耗尽的QString,实际内容不存储在QString对象中,而是存储在堆中,并且在函数返回后释放。剩下的就是一个空/null
QString


解决方案:按值返回QVariant。

如注释中所述,您正在返回一个悬空引用。所以你有未定义的行为,任何事情都可能发生

在这种情况下,QVariant保存一个整数。我的猜测是,您很幸运,保存int的内存没有被重写(或释放)

对于运气耗尽的QString,实际内容不存储在QString对象中,而是存储在堆中,并且在函数返回后释放。剩下的就是一个空/null
QString


解决方案:按值返回QVariant。

QString在按值返回或传递时不会复制其文本字符串内容。这是一种隐式共享,具有写时复制功能。假设您试图在QVariant内部“移动”QString可能会干扰隐式共享。右值引用是,您问题中的函数
getValueFromTable
正在返回对局部变量的悬空引用,从而调用UB…是否有多个
getValueFromTable()
的重载?看起来是这样。您确定
getValueFromTable(“audio_out”)
确实调用了
getValueFromTable(const QString&)
?@BenjaminT
getValueFromTable(数据库,“铃声类型”)无法调用
getValueFromTable(const QString&name)
。问题缺少另一个重载
getValueFromTable
,我认为这个重载不会通过引用返回,因此它在问题的第二个示例中有效…@BenjaminT&Mike我非常抱歉。我写错了函数。我已经更正了代码。我确信我调用了正确的函数,我已经用断点调试了代码。有人知道在哪里可以找到关于这个主题的更多信息吗?QString在返回或通过值传递时不会复制它的文本字符串内容。这是一种隐式共享,具有写时复制功能。假设您试图在QVariant内部“移动”QString可能会干扰隐式共享。右值引用是,您问题中的函数
getValueFromTable
正在返回对局部变量的悬空引用,从而调用UB…是否有多个
getValueFromTable()
的重载?看起来是这样。您确定
getValueFromTable(“audio_out”)
确实调用了
getValueFromTable(const QString&)
?@BenjaminT
getValueFromTable(数据库,“铃声类型”)无法调用
getValueFromTable(const QString&name)
。问题缺少另一个重载
getValueFromTable
,我认为这个重载不会通过引用返回,因此它在问题的第二个示例中有效…@BenjaminT&Mike我非常抱歉。我写错了函数。我已经更正了代码。我确信我调用了正确的函数,我已经用断点调试了代码。有人知道在哪里可以找到更多关于这个主题的信息吗?谢谢你的回答。所以我应该只对堆上的对象使用移动,而不是堆栈上的对象。对吗?@Szpaqn您可以移动堆栈上的对象。您不能使用对超出范围的对象的引用。特别是,这意味着您不能返回对函数本地变量的引用,因为在使用函数时,本地变量将被销毁,调用者将收到一个悬空引用。谢谢您的回答。所以我应该只对堆上的对象使用移动,而不是堆栈上的对象。对吗?@Szpaqn您可以移动堆栈上的对象。您不能使用对超出范围的对象的引用。特别是,这意味着您不能返回对函数本地变量的引用,因为在使用函数时,本地变量将被销毁,调用方将收到一个悬空引用。
int AudioSettings::getRingtoneType()  //EDIT
{
    auto value = getValueFromTable("ringtone_type");  //EDIT, I am getting a QVariant with an int inside
    return value.isNull() ? 0 : value.toInt();
}