Keyvan Kambakhsh
Keyvan Kambakhsh

Reputation: 89

Is overloading the addition operator with an rvalue reference as its left hand operand considered as a good practice?

Assuming stris a class for storing string values, it would overload the addition operator in order to support string concatenation. Like this:

str operator+(const str &a,const str &b);

But the problem is if we have something like this:

str s=str("Hel") + str("lo ") + str("Wor") + str("ld!");

Then it would create 3 temporary objects (as we get a new object in every addition) which aren't really needed in this context. A simple solution to this problem may be overloading a new addition operator which accepts a rvalue-reference as its left operand and returns this operand also as a rvalue-reference after concatenating it with the right operand. Something like this:

str &&operator+(str &&a,const str &b){
   a+=b;
   return std::move(a);
}

By having overloaded this operator, then the mentioned statement would just create a single temporary object and following additions will just be concatenated to that temporary object.

My question is, is this method a correct solution for this problem?

Upvotes: 3

Views: 818

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275790

Strings can usually be efficiently moved.

As such, your operator+ should return str not str&&. This means that

str const& bob = str1 + str2;

doesn't break horribly, or more plausibly:

for(char c : str1 + str2)

doesn't break horribly.

Second, just take a str by value. If it is an rvalue, it'll get moved in (cheap). If it is an lvalue, it will be copied (then extended, then returned). Also cheap.

str operator+( str lhs, str const& rhs )

finally, you can make the rhs be a template type of anything convertible-to-str (or valid-to-add-to-str) to remove possibly useless conversions.

In particular

str a = str("Hello") + " world";

should construct "Hello", then append " world" without constructing another str object, then move that result into a.

You could write a + that handles rvalues on both the left and right symmetrically, but that is work, and ironically chained + puts the rvalues on the left due to how chained + binds its arguments.

Finally, you can go all the way to expression templates, and do (almost) nothing until the result is assigned. This has dangers, and isn't worth it for something as simple as a toy string class. If you are writing a serious chain-of-characters class, it might be worthwhile after you had done a bunch of other improvements.

Upvotes: 5

Related Questions