Good practices

From “Effective C++”

  • Prefer const and inline to #define.
  • Prefer <iostream> to <stiod.h>.
  • Prefer new and delete to malloc and free.
  • Prefer C++ style comments.
  • Use the same form in corresponding use of new and delete.
  • Use delete on pointer members in destructors.
  • Be prepared for out-of-memory conditions.
  • Adhere to convention when writing operator new and operator delete.
  • Avoid hiding the “normal” form of the new.
  • Write operator delete if you write operator new.
  • Declare a copy constructor and an assignment operator for classes with dynamically allocated memory.
  • Prefer initialization to assignment in constructors.
  • List members in an initialization list in the order in which they are declared.
  • Make sure base classes have virtual destructors.
  • Have operator= return a reference to *this.
  • Assign to all data members in operator=.
  • Check for assignment to self in operator=.
  • Strive for class interfaces that are complete and minimal.
  • Differentiate among member functions, non-member functions and friend functions.
operator>> and operator<< are never members.
  • Avoid data members in the public interface.
  • Use const whenever possible.
  • Prefer pass-by-reference to pass-by-value.
  • Don’t try to return a reference when you must return an object.
  • Choose carefully between function overloading and parameter defaulting.
  • Avoid overloading on a pointer and a numerical type. E.g.:
void f(int x);
void f(string *ps);//*
  • Guard against potential ambiguity.
  • Explicitly disallow use of implicitly generated member functions you don’t want. E.g.:
template<class T>
class Array {
        Array& operator=(const Array& rhs);
  • Partition the global namespace.
  • Avoid returning “handles” to internal data.
  • Never return a reference to a local object or to a dereferenced pointer initialized by new within the function.
  • Postpone variable definitions as long as possible.
  • Use inlinning judiciously.
  • Minimize compilation dependencies between files.

Avoid using objects when object references and pointers will do.

Use class declarations instead of class definitions whenever you can.

Don’t #include header files in your header files unless your headers won’t compile without them.

  • Make sure public inheritance models “isa”.
  • Never redefine an inherited nonvirtual function.
  • Never redefine an inherited default parameter value.
  • Avoid casts down the inheritance hierarchy.
  • Model “has-a” or “is-implemented-in-terms-of” through layering.
  • Differentiate between inheritance and templates.
  • Use multiple inheritance judiciously.
  • Prefer compile-time and link-time errors to runtime errors.


  • Compile your sources with at least two compilers.
  • Prefer to use the standard smart pointers, std::unique_ptr by default and std::shared_ptr if sharing is needed. Use std::make_shared and std::make_unique to create smart pointer objects. [1]