Important: Please read the Qt Code of Conduct -

Implicit sharing and mutable members

  • How do you handle mutable attributes in a class that implements implicit sharing?

    A case in point: I have a class that represents a text entry. It allows properties to be set that define how the text looks, and offers a paint method to paint the text using a painter provided as a parameter, and a QRectF to paint into.

    I use this class a lot, so I implemented implicit sharing. My private data object looks like this:

    @class CGLib_TextEntryPrivate : public QSharedData
    // Constructors, Destructor omitted in this example
    // Just assume they are here and correct.

    QString m_Text;
    QFont m_Font;
    QColor m_Color;
    Qt::Alignment m_Alignment;
    qreal m_Width;
    QTextOption::WrapMode m_WordWrapMode;
    mutable QStaticText m_StaticText;
    // m_StaticText.size() is unreliable
    // therefore I do my own size calculation
    mutable QSizeF m_Size;
    mutable bool m_bStaticTextValid;
    mutable QTransform m_LastUsedTransform;


    The members m_StaticText and following are basically only caching information. I do not want to update them every time a property is changed, but as late as possible, as rarely as possible.

    This can lead to situations where I have to update them in a getter. I have the choice of either making the getter non-const (which leads to lots of problems when using the class in a const-correct code environment), or making those "caching" members mutable.
    I chose the latter. Can I run into implicit sharing troubles that way?

    The main class has, of course, a shared data pointer:
    @QSharedDataPointer<CGLib_TextEntryPrivate> d;@

    Whenever I change anything that must lead to a cache update, I call an invalidation function, which is non-const:
    @void CGLib_TextEntry::invalidateStaticText()
    d->m_bStaticTextValid = false;

    In some of the getters, I call an update function which changes only mutable members, and is const:
    @QSizeF CGLib_TextEntry::size() const
    updateStaticText(); // This is a const function I am calling

    return d->m_Size;


    I might just as well be fine with the way the class is right now: The caching information can only change after one of the non-mutable members has changed. This change must have already caused the detach to happen, which means I am updating the cache information in an object which is already detached. The question is: Are there any holes in this reasoning?

  • I don't see any holes, currently. Only the one with detach. changing members implicitly, which might affect other users of the shared object looks not the best.

    But it could work.

Log in to reply