Is a shared memory/copy on write implementation for general containers (like that found in Qt's containers) superseded by C++11 move semantics and rvalue references?
Where does one fail and the other succeed? Or are they complementary rather than alternatives?
Both copy on write and move semantics have been used to optimize value semantics of objects that hold their data on the heap. std::string
, for example has been implemented both as a copy-on-write object, and as a move-enabled object.
So copy-on-write and move semantics is similar in that regard: they can both be used to optimize "copies" if you define "copy" loosely enough. I've sometimes described move semantics as copy-on-write with the reference count being limited to 0 or 1, and thus the field containing the reference count is optimized away.
All of the containers in the std::lib now use move semantics and even std::string
, which used to be allowed to use copy-on-write, is now forbidden from doing so. If I were writing a new customer container today, I would use move semantics before choosing copy-on-write.
There is still a use for copy-on-write in C++11. If you expect your data structure to be rarely written to, but copied often, with many clients holding copies of the same value, copy-on-write can still be a large win.
For example I've seen copy-on-write put to good use to hold an undo-list for a complex document. At any given commit (where you want to save state), only a small piece of the large document has changed since the last commit. So making a copy of the document to save its state means updating a bunch of reference counts, and actually making changes (copy-on-write style) to a small piece.
Copy-on-write and move semantics are completely different concepts, each serving a different purpose. While there is a common use case: returning an object from a function, in which because the original goes out of scope it is effectively a move, in the general case they differ:
With copy on write multiple objects that are alive at the same time can share the content. With move semantics only one object has the contents in a particular point in time.
A bit orthogonal to this, copy-on-write has issues in multithreaded environments, since there are potentially multiple objects accessing the same data (read only) and control block (read/write), which needs to be managed in a thread safe manner.