Quick Q: Why is "want speed? pass by value" not recommended? -- StackOverflow

Quick A: Because it performs worse than C++98 for common types like string and vector. The preferred way to optimize for rvalues is to add a && overload.

Fresh on SO:

Why is value taking setter member functions not recommended in Herb Sutter's CppCon 2014 talk (Back to Basics: Modern C++ Style)?

In Herb Sutter's CppCon 2014 talk Back to Basics: Modern C++ Style he refers on slide 28 (a web copy of the slides are here) to this pattern:

class employee {
  std::string name_;
  void set_name(std::string name) noexcept { name_ = std::move(name); }

He says that this is problematic because when calling set_name() with a temporary, noexcept-ness isn't strong (he uses the phrase "noexcept-ish").

Now, I have been using the above pattern pretty heavily in my own recent C++ code mainly because it saves me typing two copies of set_name() every time -- yes, I know that can be a bit inefficient by forcing a copy construction every time, but hey I am a lazy typer. However Herb's phrase "This noexcept is problematic" worries me as I don't get the problem here: std::string's move assignment operator is noexcept, as is its destructor, so set_name() above seems to me to be guaranteed noexcept. I do see a potential exception throw by the compiler before set_name() as it prepares the parameter, but I am struggling to see that as problematic.

Later on on slide 32 Herb clearly states the above is an anti-pattern. Can someone explain to me why lest I have been writing bad code by being lazy?

Add a Comment

Comments are closed.

Comments (3)

1 0

R. Martinho Fernandes said on Oct 9, 2014 09:10 AM:

I really, really dislike this idea of drawing general advice from benchmarks of `std::string`. I consider it harmful. The truth is that "want speed? pass by value" doesn't "[perform] worse than C++98 for common types like `string` and `vector`".

It would be helpful if the people giving out such general advice considered more than two specific "types" when giving out such advice. In fact, it would already help a lot if at least those two "types" were considered thoroughly. It is possible to construct a not-far-fetched, totally-something-someone-would-use-in-production-code, and simple counter-example for such claims that uses no types other than "common types like `string` and `vector`". Such a counter-example is simply `vector<string>`.

So there, my "official" expression of disagreement with this campaign.
0 0

avjewe said on Oct 10, 2014 05:12 AM:

The noexcept problem is this : even though set_name is technically noexecpt, calls to set_name can throw because of the copy construction that is inserted just before the call to set_name.

The efficiency problem is this : passing an l-value to the set_name above will always create a new string and probably allocate some memory. If you pass by const reference, no new string is made and an allocation is only done if the new string is larger than any string ever held by this object.
1 0

Kristian Ivarsson said on Oct 15, 2014 07:28 AM:

Wasn't Herbs claim only valid when you reused the object (i.e. calling set_name( std::string v) several times with the same object) ? For objects where set_name( std::string v) is called only once, the by-value-pass might (in my naive world) be more efficient