Question

According to the Google style guidelines, "Few classes need to be copyable. Most should have neither a copy constructor nor an assignment operator."

They recommend you make a class uncopyable (that is, not giving it a copy constructor or assignment operator), and instead recommending passing by reference or pointer in most situations, or using clone() methods which cannot be invoked implicitly.

However, I've heard some arguments against this:

  • Accessing a reference is (usually) slower than accessing a value.
  • In some computations, I might want to leave the original object the way it is and just return the changed object.
  • I might want to store the value of a computation as a local object in a function and return it, which I couldn't do if I returned it by reference.
  • If a class is small enough, passing by reference is slower.

What are the positives/negatives of following this guideline? Is there any standard "rule of thumb" for making classes uncopyable? What should I consider when creating new classes?

Was it helpful?

Solution

I have two issues with their advice:

  1. It doesn't apply to modern C++, ignoring move constructors/assignment operators, and so assumes that taking objects by value (which would have copied before) is often inefficient.

  2. It doesn't trust the programmer to do the right thing and design their code appropriately. Instead it limits the programmer until they're forced to break the rule.

Whether your class should be copyable, moveable, both or neither should be a design decision based on the uses of the class itself. For example, a std::unique_ptr is a great example of a class that should only be moveable because copying it would invalidate its entire purpose. When you design a class, ask yourself if it makes sense to copy it. Most of the time the answer will be yes.

The advice seems to be based on the belief that programmers default to passing objects around by value which can be expensive when the objects are complex enough. This is just not true any more. You should default to passing objects around by value when you need a copy of the object, and there's no reason to be scared of this - in many cases, the move constructor will be used instead, which is almost always a constant time operation.

Again, the choice of how you should pass objects around is a design decision that should be influenced by a number of factors, such as:

  1. Am I going to need a copy of this object?
  2. Do I need to modify this object?
  3. What is the lifetime of the object?
  4. Is the object optional?

These questions should be asked with every type you write (parameter, return value, variable, whatever). You should find plenty of uses for passing objects by value that don't lead to poor performance due to copying.

If you follow good C++ programming practices, your copy constructors will be bug free, so that shouldn't be a concern. In fact, many classes can get away with just the defaulted copy/move constructors. If a class owns dynamically allocated resources and you use smart pointers appropriately, implementing the copy constructor is often as simple as copying the objects from the pointers - not much room for bugs.

Of course, this advice from Google is for people working on their code to ensure consistency throughout their codebase. That's fine. I don't recommend blindly adopting it in its entirety for a modern C++ project, however.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top