Discussion
Team LiB
Previous Section Next Section

Discussion

A common mistake (and not only among beginners) is to forget to think about copy and assignment semantics when defining a class. This happens often with small helper classes such as those meant for RAII support (see Item 13).

Ensure that your class provides sensible copying, or none at all. The choices are:

  • Explicitly disable both: If copying doesn't make sense for your type, disable both copy construction and copy assignment by declaring them as private unimplemented functions:

    
    
    class T {// …
    
    
    private:                        // make T non-copyable
    
    
      T( const T& );                // not implemented
    
    
      T& operator=( const T& );     // not implemented
    
    
    };
    
    
    

  • Explicitly write both: If copying and copy assignment is warranted for T objects, but correct copying behavior differs from what the compiler-generated versions will do, then write the functions yourself and make them nonprivate.

  • Use the compiler-generated versions, preferably with an explicit comment: Otherwise, if copying makes sense and the default behavior is correct, don't declare them yourself and just let the compiler-generated versions kick in. Prefer to comment that the default behavior is correct, so that readers of your code will know that you didn't miss one of the other two options by accident.

Note that disabling copying and copy assignment means that you cannot put T objects into standard containers. That's not necessarily a bad thing; very likely, you wouldn't want to hold such T objects in a container anyway. (You can still put them in containers by holding them via a smart pointer; see Item 79.)

Bottom line: Be proactive about these two operations because the compiler has the tendency to generously generate them, and the compiler-generated versions are often unsafe by default for non-value-like types. (See also Item 32.)

    Team LiB
    Previous Section Next Section