C++ return a std::string &
Asked Answered
G

1

9
std::string &func(int vlu)
{
    std::string str;
    str = std::to_string(vlu) + "something";

    return str;
}

the function above is unsafe clearly.
Following is another version.

std::string &func(int vlu)
{
    return std::to_string(vlu) + "something";
}  

I have some questions:
the compiler(gcc), in the second version, doesn't give me any warning. Is it safe? I just think that compiler(or something?) will create a temporary variable to hold the return of expression std::to_string(vlu) + "something". So the second version is unsafe too. and I right?

Godred answered 29/10, 2018 at 10:52 Comment(14)
clang and gcc(8.2) do emit warnings: prog.cc:5:12: error: non-const lvalue reference to type 'basic_string<...>' cannot bind to a temporary of type 'basic_string<...>' return std::to_string(vlu) + "something"; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.Keffiyeh
Yes, the second version is unsafe also. A compiler is not obligated to warn you about undefined behavior. If you get a warning, consider it to be no more than an unexpected surprise that your compiler detected your own bug for you.Burrton
The 2nd version is definitely unsafe. I think it should be a gcc bug for not emitting warning, or maybe, it involves RVO and thus affecting the analysisBernt
Possible duplicate of C++ Returning reference to local variableGenteel
its not just "unsafe". unsafe sounds as if there is a chance that it could to something wrong, but in fact there is no chance that the function could do something right...Scandalize
Yes, both examples are unsafe, in the sense that the caller will exhibit undefined behaviour if it uses the returned reference as an object (e.g. calling non-static member functions). However, the code in both functions does not contain any diagnosable error (in the sense that the standard requires a diagnostic). If your compiler gives, or can be configured to give, a warning or error for either example, count your lucky stars. Such behaviour by a compiler is a quality-of-implementation matter, not a requirement of the C++ standard.Brightwork
You should generally not use references to std:string, because they are implemented as a header pointing to the data, with only the header being copied. This from memory from the TC++PL. Anyone have an up to date reference for that?Pennate
@user463035818 - there is actually a possibility that the function will "do something right". The functions are both syntactically correct, and the behaviour is undefined if the caller uses the returned reference. However, undefined behaviour simply means the standard doesn't limit what can happen as a result, it doesn't mean that "wrong" behaviour is guaranteed. The nastiest cases of undefined behaviour occur with code that seems to work correctly, only to malfunction at some later time (such as following a compiler update, change of optimisation settings).Brightwork
@Brightwork The function itself has no undefined behaviour. It just returns an invalid reference (always), I would call this broken rather than unsafe ;)Scandalize
@Pennate that sounds strange. no references to std::string ?? huh?Scandalize
@user463035818 - You'll note that my previous comments said nothing about the functions having undefined behaviour - I referred only to the caller. It is unsafe if the caller uses that reference - because there is no way the caller can avoid undefined behaviour, no consistent way in standard C++ to even detect the presence of that undefined behaviour, and no predictable or reliable outcome. A certainty of an unknown outcome is generally considered a high risk, or a lack of safety.Brightwork
Both are bad - but more to the point, why would you want to do that?Leucotomy
@Brightwork I did note it, but the comment was adressed at me and I was also not refering to undefined behviour. Lets make a compromise and say it is unsafe to use the function because it is brokenScandalize
really there're no reasons for all this. for a mutable string from ended scope you didn't make any attempts to deploy it right. It could be done with smart pointers or with new but all stuff you'd posted looks like a bad plan part.Ives
F
13

No, neither program is safe. In both cases the returned reference is dangling and the behaviour of using the reference will be undefined.

The second program is also ill-formed, because it attempts to bind an lvalue reference (that is returned) to an rvalue (the temporary). The second program might be considered "less unsafe", since a compiler might choose to not compile it.

To fix the function: Don't attempt to return a reference, when the purpose is to return a new object. Return an object instead.

Figone answered 29/10, 2018 at 10:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.