Tip of the Week #24: Copies, Abbrv.

Originally posted as TotW #24 on Nov 26, 2012

by Titus Winters, ([email protected]) and Chandler Carruth ([email protected])

“To copy others is necessary, but to copy oneself is pathetic.” - Pablo Picasso

Note: see also TotW #55 and TotW #77 for guidance on name counting and copies vs. moves.

One Name, No Copy; Two Names, Two Copies

When evaluating whether copies get made within any given scope (including cases triggering RVO), check how many names your data refers to.

You will have two copies of the data at any point where you have two live names for those copies. To a good first approximation, the compiler will (and often must) elide copies in all other cases.

Between the move semantics of STL containers (introduced automatically with the switch to C++11) and copy constructor elision by the compiler, we are rapidly converging on this rule providing not merely a lower bound on the number of copies, but a guarantee. If your benchmarks show that more copies are being made, it is likely a compiler bug; your compiler probably needs a fix.

So if your code is structured such that there are two names for the data at some point during the execution, you should expect a copy. If you avoid introducing a name which could possibly refer to the data, you’ll help ensure the compiler can remove the copy.

Examples

Let’s look at some examples of how this works in practice:

std::string build();

std::string foo(std::string arg) {
  return arg;  // no copying here, only one name for the data “arg”.
}

void bar() {
  std::string local = build();  // only 1 instance -- only 1 name

  // no copying, a reference won’t incur a copy
  std::string& local_ref = local;

  // one copy operation, there are now two named collections of data.
  std::string second = foo(local);
}

Most of the time, none of this matters. It is far more important to ensure that your code is readable and consistent, rather than worrying about copies and performance. As always: profile before you optimize. But, if you find yourself writing code from scratch – and can provide a clean and consistent API that returns its values – don’t discount code that seems like it would make copies: everything you learned about copies in C++ a decade ago is wrong.


Subscribe to the Abseil Blog