1

I'm not sure if I should bother at all because it's not any safety critical application but I'm just curious and can't figure it out myself: will the compiler apply RVO for the following method?

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

The QJsonObject class does not implement the move constructor nor the move assignment operator. I'm using GCC 5.4 (--std=c++14) via Qt 5.9 under Ubuntu.

tomdol
  • 381
  • 3
  • 14
  • 1
    *Named* RVO might happen but the only way to know is to check the assembly. If you had a move constructor then it would be moved for you. – NathanOliver Jul 30 '18 at 13:01
  • 1
    Compilers are not required to RVO there, but the clang and gcc that I tried did. If you need moves of QJsonObject then migrate to Qt 5.10. – Öö Tiib Jul 30 '18 at 13:07
  • 1
    I tested this in Visual Studio 2017 once and found that in my case it performed NRVO in Release but not in Debug. – Mikkel K. Jul 30 '18 at 13:41
  • Thank you guys for your suggestions and actual tests, much appreciated. I will upgrade my Qt version to 5.11 tomorrow and will create a task to bump up the version in the CI servers. – tomdol Jul 30 '18 at 16:21

1 Answers1

1

The compiler is allowed to do RVO here, but it is not required to do so, cf. cppreference

If a function returns a class type by value, and the return statement's expression is the name of a non-volatile object with automatic storage duration, which isn't a function parameter, or a catch clause parameter, and which has the same type (ignoring top-level cv-qualification) as the return type of the function, then copy/move (since C++11) is omitted. When that local object is constructed, it is constructed directly in the storage where the function's return value would otherwise be moved or copied to. This variant of copy elision is known as NRVO, "named return value optimization".

So the compiler cannot optimize copying retObject when returning, but it can omit creating the temporary return value object and instead directly copy retObject to whatever MyClass::BuildObject is assigned.

Kai Guther
  • 783
  • 3
  • 11