Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang-tidy suggest I remove const references, why?

I ran clang-tidy (the "modernize" modules) on a project tree that I have been trying to keep reasonably up to date with C++17. Almost everything it corrected was unsurprising to me, except for one thing: It changed all of these types of constructs:

void foo(const std::string& str) {
}

.. to this:

void foo(std::string str) {
}

And I don't understand why. To my untrained eye this would mean two things:

  1. It would need to copy the object rather than just pass a reference. (Though I assume there are situations when the compiler can deduce that it can just pass a pointer when it generates the code -- but the reference makes it explicit (which is better imho)).
  2. The const is there to tell the function body developer that it shouldn't be changing the input string, and that if it needs to modify the string it needs to store its own copy somewhere.

I do see an upside though -- by just passing an object as a const reference it's a mere "remove const" cast away from being changed anyway, so I guess passing by value would solve that.

Why does it recommend removing const references with non-const pass-by-values?

like image 410
cypheratheist Avatar asked Apr 10 '20 20:04

cypheratheist


1 Answers

The rationale given here is

With move semantics added to the language and the standard library updated with move constructors added for many types it is now interesting to take an argument directly by value, instead of by const-reference, and then copy. This check allows the compiler to take care of choosing the best way to construct the copy.

Additionally

The transformation is usually beneficial when the calling code passes an rvalue and assumes the move construction is a cheap operation.

However, the documentation states that the only replacement is in the following specific case:

Replaces the uses of const-references constructor parameters that are copied into class fields. The parameter is then moved with std::move().

It doesn't even apply the transformation if the constructor parameter is used more than once.

So I don't think all your functions should have been transformed like that.

like image 96
cigien Avatar answered Nov 17 '22 09:11

cigien