1

Ok, I'm thinking about the following C++ code:

foo (std::string str) {
  // do whatever
}

foo(const char *c_str) {
  foo(std::string(c_str));
}

I look at this code and think it needs to be rewritten to pass by reference. Basically, my fear is that the constructor will get called twice, once in the const char * version of foo and once again when the argument is passed to foo as a std::string, since it is set to pass by copy. My question is: am I right, or is g++ smart enough to take the constructor in the c string version and call it good? It seems like g++ wouldn't be able to do that but I'm just hoping someone who really knows can clarify it.

dbeer
  • 6,963
  • 3
  • 31
  • 47

3 Answers3

1

In theory two constructors (one to create the temporary, plus the copy constructor for the pass-by-copy) would be involved; in practice, the compiler is explicitly allowed to perform copy elision (C++11 §12.8 ¶32).

But you don't need the two overloads to begin with.

The normal way to go is to just have a version of that function that takes a const std::string &. If the caller already has an std::string, no copy is performed, since we are passing by reference. If instead it has a char *, a temporary std::string is created (since it has a non-explicit constructor from const char*) and is passed to the function (since const references can be bound to temporaries).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

you can just idiomatically write

foo (std::string const& str) {
  // do whatever
}

No need for the overload, since you can implicitly construct a temporary:

foo("yes");

If you intend to store the value of the argument somewhere, you could take an rvalue reference:

foo (std::string && str) {
   my_member = std::move(str);
}

But to avoid overload explosion, taking the argument by value is often a good middleground:

Regardless of all this good avice about idomatic parameter-passing, yes the compiler can optimize away the spurious copies under the as-if rule (although the copy constructor is required to be accessible as if the copy were performed)

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
0

Since the temporary passed to foo is unnamed it seems like it would be a fairly simple optimization to construct directly into the parameter, eliminating the copy, although this isn't guaranteed by the standard (as no optimizations are).

More generally speaking however, you should pass by constant reference unless your function would be taking a copy of the parameter itself already (perhaps to copy-and-mutate for example),

Mark B
  • 95,107
  • 10
  • 109
  • 188