How to use QStringView (or QStringRef) in Qt widgets?

Viewed 2361

I'm trying to replace heavy QString class with the lighter alternatives (QStringRef/QStringView). The problem is that Qt widgets don't consume these classes by any mean. For example, the QLabel::setText method requires const QString& as an input parameter, making my improvement useless.

I'm confused with this discrepancy. Is that on purpose? Is there any reason for that? What should be the use case for QStringView if at the end of the day no one consumes them?

2 Answers

QString, QStringRef and QStringView have different use cases:

  • QString: the default class to store a string in Qt. It uses implicit sharing to avoid unneeded (read only) copies. Note that you may construct it efficiently by using f.ex. QStringLiteral for static strings:

    [...] For most purposes, QString is the class you want to use. It is used throughout the Qt API [...]

  • QStringView: is useful as a function parameter when you do not want to store the string (and care about the overhead of constructing a QString):

    QStringView is designed as an interface type; its main use-case is as a function parameter type. When QStringViews are used as automatic variables or data members, care must be taken to ensure that the referenced string data (for example, owned by a QString) outlives the QStringView on all code paths, lest the string view ends up referencing deleted data.

    If you want to give your users maximum freedom in what strings they can pass to your function, accompany the QStringView overload with overloads for [...] QString if you store an unmodified copy of the string and thus would like to take advantage of QString's implicit sharing.

    QLabel should definitely store the text string (to paint it during the paint event or to implement the getter function). So, providing a QStringView overload wouldn't be an improvement.

  • QStringRef: is useful for low-level string parsing:

    This class is designed to improve the performance of substring handling when manipulating substrings obtained from existing QString instances. QStringRef avoids the memory allocation and reference counting overhead of a standard QString by simply referencing a part of the original string. This can prove to be advantageous in low level code, such as that used in a parser, at the expense of potentially more complex code.

Note that only QString takes ownership of the string, for the other two, it is the programmer who should ensure the referenced string still exists.

Conclusion: QString is the right class to use in the interface of QLabel::setText.

Further reading

Qt uses CoW (Copy-on-Write) principle for its own containers. It is a bit outdated technique, but works ok for a mostly single thread UI framework like Qt.

The official documentation eleborates more on that here: https://doc.qt.io/qt-5/implicit-sharing.html

As @m7913d noted in the comments and in his answer, most widgets do create a local copy inside and that is when the CoW principle makes things fast.

Anyway, we are dealing with UI here, lots of drawing, OS API, abstraction layers, giant (compared to string sizes) framebuffers and what not. May be they will add StringViews to their API later and change their architecture, add SSO for QStrings, but apperently this is not an emergency now.

Qt used to be progressive like 10-15 years ago. CoW, Qt containers, lots of libs for everyday things, usability. But now all this stuff is lagging behind modern C++ and STL and Qt encourages their users to rely on STL containers and use Qt analogs only for operations with API.

No one wants a parallel STL and a Qt version of every lib ever.

As for QStringView I think its purpose is to provide a modern view mechanism for user classes which interact with QStrings. For example, you use QXML to extract lots of data from xml files. And then you have to analyze this data somehow - you do not need to interact with API, but you already have QStrings. To make things up to date and a bit faster - here you are - QStringView.

Related