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.