Mar 27, 2017

[C++] Better Code: Runtime Polymorphism - Sean Parent - note


  • Write all code as a library.
    • Reuse inceases your productivity.
    • Writing unit tests is simplified.

 
Shared_ptr are just as good as global variable...

Value semantics
Reference semantics
  • Polymorphc types:
    • By using inheritance to capture polymorphc use, we shift the burden of use to the type implementation, tightly coupling components
  • Inheritance implies variable size, which implies heap allocation.
  • Heap allocation forces a further burden to manage the object lifetime.
  • Indirection, heap allocation, and virtualization, impacts performance.
  • Object lifetime management leads to garbage collection or reference counting.
  • This encourages shared ownership and the proliferation of incidental data-structure.
  • Shared ownership leads to synchronization issues, breaks local reasoning, and further impacts performance.

 
That is, inheritance is the base class of evil.


Guideline:
  • Write classes that behave like regular objects to increase reuse.
  • Do your own memory management, don't create garbage for your client to clean up.

 
Copy constructor guideline:
  • The semantics of copy are to create a new object which is equal to, and logically disjoin from, the original.
  • Copy constructor must copy the object. The compiler is free to elide copies so if the copy constructor does something else the code is incorrect.
  • When a type manages remote parts it is necessary to supply a copy constructor.
  • If you can, use an existing class(such as vector) to manage remote parts.

         
Assignment operator:
  • Steal the guts of that copy!
  • Assignment is consistent with copy. Generally:

        T x; x=y; is equivalent to
        T x = y;
     

  • Assignment satisfying the strong exception guarantee is a nice property.
  • Either complete successfully or throw an exception, leaving the object unchanged.
  • Assignment (like all other operations) must satisfy the basic exception guarantee.
  • Don't optimize for rare cases which impact common cases.
  • Don't test for self-assignment to avoid the copy.
  • The private implementation(Pimpl), or handle-body, idom is good for separating the implementation and reducing compile times.
  • Pass sink arguments by value and swap or move into place.
  • A sink argument is any argument consumed or returned by the function.
  • The argument to assignment is a sink argument.
  • However, because of a language defect, you must write a move assignment operator(explain below.)

     
Remember to provide move constructor!
  • Provide a move constructor and move assignment to avoid copies and get fast permutations.
  • Prior to C++11, provide a swap() function.
  • Use '=default' when possible.
  • Include the expected exception specification to catch mistakes.

Language defect:
  • IFF data member or direct base class with a type that does NOT have a move assignment operator and is NOT trivially copyable, the type's defaulted copy/move assignment operator for class X is defined as deleted.

        也就是,將一般的operator=(type x)
        內容寫成movable並沒有用!
        一定要有move assignment operator:
        operator=(type&& x)
     

  • Don't allow polymorphism to complicate the client code.
  • Polymorphism is an implementation detail.
  • The runtime-concept idiom allows polymorphism when needed without inheritance.

  • A shared pointer to an immutable(const) object has value semantics.
  • This is why passing arguments by const& works.
  • Observation: Mutable polymorphism objects are the exception.
  • Copy-on-write can be obtained using shared_ptr::unique()


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.