2

I had this discussion with a colleague of mine on this. And would like to know the opinion of more folks as to which is "can" be more optimal? PS: If the code is just a hello world program, the -O3 results in identical code, but we are talking of a scenario where this code segment is in the middle of a large project.

4
  • 6
    What makes you think the optimizer handles this differently in your hello world program than in the middle of a large project? Commented Sep 27, 2012 at 21:27
  • What about const char* a = "tmp"; or even char a[] = "tmp"; This could be faster ;) Commented Sep 27, 2012 at 21:30
  • The point is not to make the code fast. Both of us agree that neither of this would help. Its just a discussion :) Commented Sep 27, 2012 at 21:33
  • @nightcracker I am not sure, but register pressure and lot more instructions to prioritize/optimize may lead to some difference. I am not expert on this, please correct me if I am wrong. Commented Sep 27, 2012 at 21:49

2 Answers 2

4

Context would be of deciding importance. And your profiler would probably tell you to not sweat it.

In this case, a new std::string has to be constructed anyways, and the 'const reference to life-time-extended temporary value' would really only cause the compiler more work (to emit equivalent/identical code).

I'd opt for clarity:

Code intent, not method

So

std::string tmp("Hello");

Or

std::string tmp = "Hello"; 

would express the intent fully.

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

Comments

2

Chances are that the compiler will generate the same code, but using a reference is misleading to casual readers. Consider that instead of initializing it with a literal you used the return of a function:

std::string f();

std::string const & r = f(); // [1]

The line tagged as [1] seems to just be creating a reference (low cost operation) to an object managed somewhere else. The reader of the code will be left trying to figure out whether the referenced string can change externally or even if it might be destroyed leaving a dangling reference. They will have to go to the documentation of f() and find out that it is actually a temporary, and then back to the original code and figure out that this was just some programmer playing smart tricks.

On the other hand std::string s = f(); is much clearer on the intent: Whatever f() represents, a copy of that will be maintained in the local context. The object will not change externally and the lifetime is exactly the scope in which it is defined.

Note that in both cases the behavior is really the same, but in one case it is obvious to the casual reader, while in the other the reader must figure it out. I would use local objects in all cases where I can, and limit the lifetime extension to the few cases where the value won't cut it (which in real life I have only needed once).

10 Comments

I like this angle of approach too: basically the same: express intent, but this time, more focus on human readers as well. +1
Thanks for the inputs. I understand the importance of making your code readable to others. But from a completely personal POV I feel returning std::string from functions is not the best way. Reason the function can return an enormously long string which doesn't make any sense to make a local copy. It may be good when there is a well-defined agreement between the caller and callee about the length of such a string.
@Game: You are wrong in your assumption. If you are returning a reference to an existing std::string, then yes, the cost will be higher when returning by value. But if you are creating a std::string inside your function then you must return it by value. The extra copies will be elided (i.e. the string created inside the function and the returned string will be the same object) in most cases, and when that is not possible (and in C++11 only) the contents will be moved, which is a low cost operation. Consider for example operator+ when applied to strings, it returns by value.
Again, if the function does return a reference it makes sense to hold a reference, but if the function returns by value then you should store it in a local object, not use the lifetime extension hack. Note that this is the main point in the answer: not focusing on the design of f(), but given an f() that does return by value, which option to use on the call site.
Sorry to bother you (if it is) if the function is returning a locally constructed value, I believe the best way to have the signature is void/bool fun(string* a); rather than string fun(); Again, readability has to be compromised. I know about copy elision, but I feel if we can avoid it through signature we should. You can count on compiler optimizations, not depend on them.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.