Hands-On High Performance Programming with Qt 5
上QQ阅读APP看书,第一时间看更新

Implicit sharing

The first thing that catches the eye is that Qt containers support implicit sharing, which is a fancy name for a combination of reference counting and copy-on-write (COW). Let's have a look at the inner structure of a typical Qt container, as depicted in the next figure:

The container itself is a thin wrapper around the pointer d, which points to its real data. The payload data is preceded by a header containing a reference count, the allocated size, and sometimes further optional data, such as the used size and flags. Now, when a container gets copied only a shallow copy will take place, so that the two containers will share the data, as shown in the next figure:

When Container 2 will try to change some of its data now, the detach() operation will be executed, performing a deep copy of the container's data, before changing the value in the copied data buffer, as demonstrated in the following diagram:

In cases when the data is not changed after copying, it will be freed when the reference count falls back to zero. To be frank, the deep copy will be done not just if the container's data has actually been changed, but also on every invocation of a non-const member function. So, watch out for those accidental copies! We will discuss that in more detail in the forthcoming Iterators and iterations section, which discusses iterating over containers.

This implementation technique was used when there wasn't yet the support for move semantics in the language, to optimize out the creation of temporaries, which we discussed in Chapter 3, Deep Dive into C++ and Performance. For example, the GCC implementation of std::string used it before C++11.

By the way, if you'd like to implement your custom implicit-sharing data structures, you can use the two Qt helper classes QSharedData and QSharedDataPointer<T>.