34

I'm looking over some code, and all the calls to a function returning a string are assigned to a reference. The function prototype something like:

 std::string GetPath(const std::string& top);

and it's used as

std::string& f = GetPath(cw);

or

 const std::string& f = GetPath(cw);

Why would one use a reference here instead of

 std::string f = GetPath(cw);
Anonym
  • 7,345
  • 8
  • 35
  • 32
  • 12
    Not a duplicate at all actually. They just both involve references. If that a duplicate makes then half of the C++ questions on SO should be closed (which may indeed be the case, but for other reasons). – Edward Strange Jan 13 '11 at 20:09
  • I recommend you clarify: Do you ask also about functions that not only return *values* but also *references*? – Johannes Schaub - litb Jan 14 '11 at 11:22
  • Possible duplicate of [Store return value of function in reference C++](https://stackoverflow.com/questions/2822243/store-return-value-of-function-in-reference-c) – bobobobo Nov 03 '21 at 15:04
  • Also related: [rvalue reference and return value of a function](https://stackoverflow.com/questions/21711825/rvalue-reference-and-return-value-of-a-function) – bobobobo Nov 03 '21 at 15:10

3 Answers3

31

If the function returned a reference (which it doesn't) then you might want to assign the return value to a reference in order to keep "up to date" with any changes to that object. The reference returned would have to be to an object with a lifetime that extended beyond the end of the function.

Or (if the returned reference was not-const) because you wanted to keep a reference to the object to mutate it as a subsequent point. (If you wanted to mutate it immediately you would do it directly, no need to store the reference.)

As the function returns a value you could assign it to a const reference (to a non-const reference would be illegal) and extend the object's lifetime to the lifetime of the reference. However the effect would be exactly the same (const aside) as storing the value in a object directly.

Any thought that it might be less efficient may well prove unfounded and you can qualify the object with const if you want as well. (Most compilers eliminate the implied temporary and construct the return value in the object being initialized.)

As the object type is returned from the function by value it must be copyable so this is no reason to use a reference because of a concern that it isn't.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 11
    Wow, and you didn't even have to add baseless insults! – GManNickG Jan 13 '11 at 20:39
  • 1
    I might be outing me as a old man (who knew?), but last time I looked, binding temporaries to const references was a nice, cheap optimization trick only jealously shared. I can see that move semantics will render it pretty useless, but what happened to C++03 that made this "misguided"? – sbi Jan 13 '11 at 21:21
  • 2
    If the author of the code had been known, the above would be quite insulting. It portrays the code's author as "misguided" and with "fear". And believing that about the author, doesn't help the OP. In contrast, saying the code's author is incompetent or stupid, is just a plain assessment. It helps the OP by knowing not to trust that there are good reasons for any of the rest of the code. – Cheers and hth. - Alf Jan 13 '11 at 21:26
  • @sbi: Which "optimization trick" are you referring to? There is a semantics trick that is very similar, used for e.g. scope guards, but I know of no optimization trick. So, what exactly are you thinking of? – Cheers and hth. - Alf Jan 13 '11 at 21:29
  • 5
    @Alf: "Misguided" isn't an insult. It just means "acting in error". We all make mistakes, this isn't anything new. Contrarily, "stupid" and "incompetent" receive differing treatment because they are used to degrade and demoralize a person, not mention they're acting in error. And "fear" isn't an insult either. It just means "wary", "concerned", or "careful"; are we not to be careful? No, the difference between the answers is casual and non-malicious reading of this answer yields no insults while yours presents them on the forefront. – GManNickG Jan 13 '11 at 21:42
  • 1
    @Alf: Also, sbi has demonstrated that he thinks this kind of code is worthwhile. Why aren't you calling him stupid or incompetent to him directly? Do you only do that to people who cannot respond? Very mature. – GManNickG Jan 13 '11 at 21:43
  • @GMan: it's ungood of you to start spewing out hypothetical ungood motivations of people here, especially when you hypothesize those motivations as reasons for doing Bad Deeds that haven't even been done. It's sneaky, it's underhanded, it's really bad. Don't do it. – Cheers and hth. - Alf Jan 13 '11 at 21:49
  • @Alf P. Steinbach: I have toned down my answer. I hope that it is still reasonably accurate and helpful and can't be misinterpreted as an insult to either the question asker or the original author of this code or any code like it. – CB Bailey Jan 13 '11 at 21:52
  • 1
    @Alf: That's possibly one of the most obscure and vague sentences I've ever read. Can I ask you clarify your response? I'll clarify my question: When someone thinks that binding to a const-reference is useful (the author of OP's code), you call them stupid and incompetent. When sbi does it, then, should he not be called stupid and incompetent? At least answer: do you believe it's the case? Surely if you're going to call an unknown person stupid, you can call a known person stupid, or surely, if you're consistent, you believe sbi to be stupid. – GManNickG Jan 13 '11 at 21:54
  • @GMan: You choose to believe that sbi doesn't know what binding to a reference entails, a quite basic thing. I chose instead to ask what he referred to. Perhaps that illustrates a difference between us? – Cheers and hth. - Alf Jan 13 '11 at 22:05
  • @Alf: It does, but that difference is unimportant compared to that other one. – sbi Jan 13 '11 at 22:10
  • 1
    @Alf: You said on your answer: "a reference confers no advantage, and it obfuscates, ..." and "...this is at the bottom level, the most basic knowledge...". You then said: "...then the author of the code can not be competent." sbi has expressed *either* we doesn't understand references, doesn't understand why they aren't useful here, or that he doesn't know enough to express his use clearly, all which are basic, according to you. So according to you, he's stupid and incompetent, while according to everyone else, he's just someone who's trying to learn and doesn't deserve insult. (@Ch Delete?) – GManNickG Jan 13 '11 at 22:12
  • @GMan: I find your attempted proof that sbi is incompetent, quite lacking. – Cheers and hth. - Alf Jan 13 '11 at 23:37
  • @Alf: By your definition of incompetent, mind you, not in general. I certainly don't find sbi incompetent. What's lacking about it? Or should I just say "I find your retort quite lacking" and continue to think I'm correct, without ever demonstrating why your retort is lacking? – GManNickG Jan 13 '11 at 23:54
  • @GMan: in a court, to demonstrate sbi's incompetence, you'd have to produce code provably written by him, in some recent time, with constructions like the one we're talking about. as it happens, sbi has explained elsewhere that he referred to measurements with some early 1990's compiler that did a poor (and arbitrary) optimization job. the code above, using namespace std, can't be from that era. – Cheers and hth. - Alf Jan 14 '11 at 00:08
  • @Alf: (Again, in your court.) Your definition of incompetence was based on *understanding*, yes? And you used code to judge someones understanding. sbi above provided information to us that allowed us to judge his understanding, code isn't necessary for this. So your claim about *needing* code is wrong. Do we agree here? – GManNickG Jan 14 '11 at 00:25
  • @GMan: no, we don't agree. for example, the code we're discussing is a premature optimization, at some cost. i don't think sbi would make such premature optimization. if he considered it, i think it would only be after measuring. then he would measure the hopefully optimized code and discover that old early 1990's measurement with quirky compiler didn't apply. so i don't think he would hand out that code. you think so. i disagree. – Cheers and hth. - Alf Jan 14 '11 at 00:32
  • @Alf: I never said I think he'd "hand out that code", can you please locate that for me? – GManNickG Jan 14 '11 at 00:41
  • @GMan: all right, you thought actually producing the code didn't matter, only the lack of understanding that went into producing it. but that lack of understanding involves much more than a misconception about typical optimization. it involves blithely acting on the misconception, doing premature optimization, without checking. nobody knows everything. but competent people don't (in general) do unusual things without good reason and checking that it makes sense. – Cheers and hth. - Alf Jan 14 '11 at 00:46
  • @Alf: That's fine and I agree, but is it not the case that when sbi made his comments, he was demonstrating that he had, unbeknownst to him, a misconception and *hadn't* considered it, so was acting on it without checking? – GManNickG Jan 14 '11 at 00:49
  • @GMan: no he wasn't acting, just asking. and besides, the guy who wrote the original code did things that are *invalid* in standard C++, and sbi had no misconception about that. so out of three (invalid binding, optimization, premature optimization) sbi was asking about the optimization thing. does not fit my idea of incompetent. – Cheers and hth. - Alf Jan 14 '11 at 00:52
  • @Alf: You don't pick up from his comment that he used references in this pre-optimizing fashion? – GManNickG Jan 14 '11 at 00:56
  • @sbi: how is it an optimization trick ? The object has to be built somewhere anyway. The *perceived* lack of copying is misguided, because it does not take into account that RVO could probably kick in, and the syntax hide the fact that a temporary is out there. Worse, binding-to-const may actually create bugs: try returning the const-reference, gcc does not emit a single warning but I can assure you the code may crash --> I was on the receiving end when it happened in some of our code (fortunately in test env). – Matthieu M. Jan 14 '11 at 07:40
  • Let's be careful about the term "temporary". Let's prefer "rvalue". By the very nature of how binding to a ref-to-const works, your RHS expression is not really a temporary at all. – Lightness Races in Orbit Jan 14 '11 at 11:02
  • The term "temporary" has a dual nature in the Standard, as has the term "bit-field". Both terms apply to both entities (a bit-field is a member of a class, and a temporary is an object) and expressions (an expression can be classified as a "bit-field lvalue" and as a "temporary rvalue"). Only in the context of description, it's clear what is meant. For example, binding ref-to-const to temporaries, the description talks about temporary expressions. – Johannes Schaub - litb Jan 14 '11 at 11:26
  • @JohannesSchaub-litb: Go on, pull me up on the use of "store the reference". I mean, of course, bind a reference to the _lvalue_ returned by the function. – CB Bailey Jan 14 '11 at 11:34
  • 1
    Charles, I didn't notice any mistakes you did in your answer. So for any issues you find in your answer, I don't want to claim any credits. Just fix them if you think they are severe enough, or leave them alone if you don't. My comment was in response to @Tomalak. I'm sorry for having missed proper @-signs lol. – Johannes Schaub - litb Jan 14 '11 at 11:51
4

This is probably an overzealous optimization aimed at cases where function being called returns a reference, as in:

const std::string& func();
...
const std::string& tmp = func();
...

to save on string copy.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • This answer would be better if you noted how pointless it is to be doing such a thing but yes, you've probably nailed down the motives. – Edward Strange Jan 13 '11 at 23:07
  • 1
    Hmm, I don't think this is completely pointless. I think there are corner cases where you might want to do this in C++98. – Nikolai Fetissov Jan 14 '11 at 02:54
-4

Ok, it's completely pointless. And looks awful. And not valid c++. Just don't do it.

Edit: for better understanding of what I mean

reference & var = funcNotReturningReference(); //invalid C++
const reference & cvar = funcNotReturningReference(); //silly C++, no saving costs (reference to temporary stops temporary from being released, but this code does not help anything)
peenut
  • 3,366
  • 23
  • 24
  • I bet you get +20 for that. Kudos. – Edward Strange Jan 13 '11 at 20:13
  • 1
    -1. `const std::string& result = function();` is perfectly valid C++. – Lightness Races in Orbit Jan 13 '11 at 20:16
  • 3
    It's always better to reason, than insult. – peenut Jan 13 '11 at 20:18
  • @peenut: I agree. Unfortunately, your reasoning is flawed. :) – Lightness Races in Orbit Jan 13 '11 at 20:23
  • @peenut It's still flawed. `struct Foo { std::string str; Foo() : str("Long string here") {} }; Foo f; Foo& bar() { return f; } /* ... */ const Foo& ref = bar();` may *very well* give you costsavings. If you use a very complex object rather than an `std::string`, then the saving costs *could* be significant. I'm not saying that they always will be, just that they could be. All this "this is always pointless and stupid" that's floating around this question is baseless, and a sad way to generalise what is actually quite a complex topic. – Lightness Races in Orbit Jan 14 '11 at 11:06
  • @Tomalak the question wasn't about a function that returns a reference. It asked about return values (not lvalues, it's arguable whether an lvalue is a "value" or not - I think it is not, even though the Standard sometimes "abuses" the term "value" to include lvalues, and sometimes it doesn't. I love the clarity in the Java spec!) and a function having `string` return type. I suspect if the questioner meant something else he should clarify his intent, because now both this answer, @Alf's answer, @Charles' and my own interpretation disagree with what you perceive from the question. – Johannes Schaub - litb Jan 14 '11 at 11:17
  • @Johannes: What? Where did the OP specify the return type of the function? (I don't trust his phrase "returning a string" to be 100% guaranteeing it's a return by value, although I'll admit that I missed the phrase completely until now) My point is that it *could* return a reference. – Lightness Races in Orbit Jan 14 '11 at 11:21
  • @Tomalak I've asked the OP to be more precise now. – Johannes Schaub - litb Jan 14 '11 at 11:23
  • @Johannes: "And not valid C++" is completely false, as written. To each his own though, I guess. – Lightness Races in Orbit Jan 14 '11 at 11:29
  • @Johannes: As you have just informed me elsewhere, even the standard uses the phrase "returning a T" to mean a return type of "T&" sometimes. So I stand by my point that, although everyone's assuming a return-by-value and therefore a pointlessness of binding to a ref[-to-const], there is still a possible use case here. – Lightness Races in Orbit Jan 14 '11 at 11:34
  • @Tomalak I think he clarified what he meant: Binding a non-const-ref to the `string` value returned by the function is illegal C++. I agree if you are *really* pedant you can still say `struct A { operator int&() { static int n; return n; } }; A f() { return A(); } int &r = A();`, but I don't think anyone wants to go there. I think it's a badly worded question at most, but I upvoted because I don't think it deserves a -3. Anyway, the Standard just uses "yielding T" *and* then says it means also `T&` (and "yield" and "returns" isn't the same IMO: "yields" could be read as "yields expression"). – Johannes Schaub - litb Jan 14 '11 at 11:38
  • @Johannes: I think that you are confusing the question with the answer, both when reading my comments and when writing yours! – Lightness Races in Orbit Jan 14 '11 at 11:41
  • @Tomalak oh you are right I wanted to say "answer" in my last comment (with this comment included, in my second last). But It seems that was the only comment I made that mistake in. In any case, I think we can hardly argue from a few Standardese texts that *also* include normative clarification that the issue at hand is unambiguous. I think it's ambiguous; that's why I asked the questioner (really the questioner now) that he shall clarify his question. – Johannes Schaub - litb Jan 14 '11 at 11:45
  • @Johannes: I think that is very wise, as usual. :) – Lightness Races in Orbit Jan 14 '11 at 11:48