【问题标题】:Will RVO work in this case?RVO 在这种情况下会起作用吗?
【发布时间】:2018-07-30 12:48:03
【问题描述】:

我不确定我是否应该打扰,因为它不是任何安全关键应用程序,但我只是好奇并且自己无法弄清楚:编译器会为以下方法应用 RVO 吗?

QJsonObject MyClass::buildObject(const QVector2D& position, const QString& id) const
{
    QJsonObject retObject {
        {"Position", QJsonArray{position.x(), position.y()}},
    };

    if (!id.isNull() && !id.isEmpty())
    {
        retObject.insert("Id", id);
    }

    return retObject;
}

QJsonObject 类没有实现移动构造函数,也没有实现移动赋值运算符。我在 Ubuntu 下通过 Qt 5.9 使用 GCC 5.4 (--std=c++14)。

【问题讨论】:

  • Named RVO 可能会发生,但唯一知道的方法是检查程序集。如果你有一个移动构造函数,那么它将为你移动。
  • 那里的 RVO 不需要编译器,但我尝试过的 clang 和 gcc 可以。如果您需要移动 QJsonObject,请迁移到 Qt 5.10。
  • 我在 Visual Studio 2017 中测试过一次,发现在我的情况下它在 Release 中执行了 NRVO,但在 Debug 中没有执行。
  • 感谢大家的建议和实际测试,非常感谢。我明天会将我的 Qt 版本升级到 5.11,并将创建一个任务来提升 CI 服务器中的版本。

标签: c++ qt copy-elision rvo


【解决方案1】:

这里允许编译器执行 RVO,但不是必须这样做,参见。 cppreference

如果函数按值返回类类型,并且return语句的表达式是具有自动存储持续时间的非易失性对象的名称,它不是函数参数或catch子句参数,并且具有与函数的返回类型相同的类型(忽略顶级 cv 限定),则省略复制/移动(C++11 起)。当构造该本地对象时,它直接在存储中构造,否则函数的返回值将被移动或复制到该存储中。这种复制省略的变体被称为 NRVO,“命名返回值优化”。

因此编译器在返回时无法优化复制retObject,但它可以省略创建临时返回值对象,而是直接将retObject复制到分配的MyClass::BuildObject

【讨论】:

  • 一点点吹毛求疵:这种复制省略的变体被称为 NRVO,“命名返回值优化”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
相关资源
最近更新 更多