【问题标题】:Passing rvalue reference to QVariant does not work with QString将右值引用传递给 QVariant 不适用于 QString
【发布时间】:2018-01-19 15:32:41
【问题描述】:

我正在尝试将一个右值引用从一个函数返回到一个 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();
}

当我打电话时:

QString &&AudioSettings::getAudioOut()
{
    auto value = getValueFromTable("audio_out");  //here I get an invalid QVariant
    return value.isNull() ? QString() : value.toString(); 
}

有效的是:

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();
}

有人知道为什么吗?

【问题讨论】:

  • QString 在返回或按值传递时不会复制其文本字符串内容。它是一种隐式共享,写入时复制。鉴于您尝试在 QVariant 中“移动”QString 可能会干扰隐式共享。
  • 右值引用是still a reference,您问题中的函数getValueFromTable 正在返回对局部变量的悬空引用并因此调用UB ...
  • 你有几个getValueFromTable() 的重载吗?它看起来像。你确定getValueFromTable("audio_out") 确实打电话给getValueFromTable(const QString&amp;) 吗?
  • @BenjaminT getValueFromTable(database, "ringtone_type"); 就是不能打电话给getValueFromTable(const QString &amp;name)。该问题缺少getValueFromTable 的另一个重载,我认为此重载不会通过引用返回,因此它适用于问题的第二个示例...
  • @BenjaminT & Mike 非常抱歉。我写错了函数。我已经更正了代码。我确信我调用了正确的函数,我已经用断点调试了代码。有人知道在哪里可以找到有关此主题的更多信息吗?

标签: qt rvalue-reference qstring qvariant stdmove


【解决方案1】:

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

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

对于QString你的运气用完了,实际内容并不存储在QString对象中,而是存储在堆上,一旦函数返回就被释放。剩下的就是一个空/null QString

解决方案:按值返回 QVariant。

【讨论】:

  • 感谢您的回答。所以我应该只对堆上的对象使用移动,而不是堆栈上的对象。对吗?
  • @Szpaqn 您可以移动堆栈上的对象。您不能做的是使用对超出范围的对象的引用。特别是这意味着您不能返回对函数本地变量的引用,因为在函数存在时本地变量将被销毁,而调用者将收到一个悬空引用。
猜你喜欢
  • 2014-09-09
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多