0

I was wondering about a more theoretical than practical question - what's the best way to return a value from a function? I can do something like this

std::string foo(void) { std::string buf = "Hello World" + to_string(1); return buf; } 

Or I can do like this

std::string bar(void) { return "Hello World" + to_string(1); } 

I know the output will be the same, but whats's the "better" way? Or is it the same for the compiler?

2 Answers 2

2

It's mostly a matter of style.

But there are subtle differences because of copy elision.

Since C++17 when returning a prvalue (your case return "Hello World" + to_string(1);) the compiler must do copy elision because/return value optimization. In your case with return buf the compiler can do copy elision/named return value optimization, but it is not obliged to do so.

In C++11 and C++14 both copy elision where possible but not mandatory.

Without copy elision you will have a local variable buf or a local temporary ("Hello World" + to_string(1)) which will be copied on return. With copy elision there will not be a local object. buf or the temporary will be created at the place where the caller wants to store the object.

That can lead to effects like observed here where the address of the local object is the same as the address of the returned object (on caller site).

So to make it short with the temporary you will definitely get copy elision and thus better performance. With buf you might get copy elision, but you might also not get and thus lower performance. As always if performance is critical you should measure it. If the performance is not critical here I would just prefer whichever code looks clearer to you (or maybe just better fits the line length limits).

Sign up to request clarification or add additional context in comments.

1 Comment

That said, many implementations have used named return values optimization (NRVO) for a long, long time. While NRVO is not mandated, in practice the code generated by the two options will be identical across almost all modern implementations.
2

For both cases copy elision might be performed for the return statement, the copy/move operation might be elided.

For the 1st case,

In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".

For the 2nd case,

In a return statement, when the operand is a prvalue of the same class type (ignoring cv-qualification) as the function return type:

Since C++17, the 2nd one is mandatory.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.