Objective
Achieve the optimization purpose of the deferred copy (lazy copy). Similar to deferred initialization (lazy initialization), the choice is more effective at the right time.
Alias
- COW (Copy-on-write)
- Lazy Copy
Motivation
Copying objects can sometimes result in a performance penalty (performance penalty). If objects are frequently copied, but with little modification, copy-on-write can significantly improve performance. In order to implement Copy-on-write, a smart pointer is needed to encapsulate the true object values, and each time you modify it, check the object's reference count. If the object is referenced more than once, a replica is created before the modification.
Solutions and examples
#ifndef cowptr_hpp#define cowptr_hpp#include <memory>Template <class T>class cowptr{ Public: typedef std::shared_ptr<t> REFPTR;Private: Refptr m_sp;voidDetach () {t* tmp = m_sp.Get();if( ! (TMP = =0|| M_sp.unique ())) {m_sp = Refptr (NewT (*tmp)); } } Public:cowptr(t* T):m_sp(t) {} cowptr (Constrefptr& refptr): m_sp (refptr) {}Constt&operator*()Const{return*M_SP; } t&operator* () {detach ();return*M_SP; }Constt*operator()Const{returnM_sp.operator(); } t*operator() {detach ();returnM_sp.operator(); }};#endif
译注:原文代码使用boost库,都改为std的实现了。
This is a simple implementation version. In addition to having to refer to its internal objects through a smart pointer dereference (dereferencing), there is at least one drawback: a class can return a reference to an internal state:
char & String::operator[](int)
This will carry some unexpected behavior.
Consider the following code snippet:
CowPtr<std::stringnewstd::string("Hello");char &c = s1->operator[](4// 非常量的detach操作什么也不做CowPtr<std::string// 延迟拷贝,共享的状态‘!‘// 悲催啦
The last line was meant to modify the original string instead s1
of its copy s2
, and in fact it s2
was modified.
A good practice is to write a custom copy-on-write implementation that encapsulates a class that requires a deferred copy (lazy-copy) and remains transparent to the user. To solve the above problem, you can mark the object as "non-shareable (unshareable)" status to indicate that a reference to the memory object has been surrendered, that is, to force a deep copy. Further optimizations can revert to a "shared (shareable)" State after non-const operations that do not abandon the internal object reference (for example, ' void String::clear ())) because the client code expects these references to be invalidated.
This part is not clearly said. Tag objects are not shareable, such as in the example above, after removing the character C is set to not be shared, and then construct the S2 directly deep copy. In addition, the non-const operation does not abandon the internal object, which refers to the creation of a replica of this type of operation, when the original object can be updated to shareable.
Known applications
- Active Template Library
- Many Qt classes (implicit sharing)
Related Idioms Reference
- Herb Sutter, more exceptional C + +, Addison-wesley 2002-items 13–16
- Wikipedia:copy-on-write
For more translations, please visit the GitHub project.
[Ood-more C + + idioms] Write-time copy (copy on write)