Reputation: 333
char*[]
object can be passed to function version2() & version 3() by the const reference, which means s2 is a temporary object equals to "###" or "@@@".
But why the temporary object s2 can be returned back, while the temporary object temp cannot.
int main()
{
result = version2(input, "###");
cout << "Your string enhanced: " << result << endl;
result = version3(input, "@@@");
cout << "Your string enhanced: " << result << endl;
return 0;
}
// No Error
const string & version2(string & s1, const string & s2)
{
return s2;
}
// Error
const string & version3(string & s1, const string & s2)
{
string temp = s2 + s1 + s2;
return temp;
}
Upvotes: 1
Views: 299
Reputation: 10591
I would say it just because the compiler doesn't think version2
is dangerous.
Note that for version3
, it actually gives a warning, not error (unless you tell it to).
In fact if you change it to catch result by reference, there would still no warning, but the temporary is no doubt have been destroyed. you can check the assembly (or standard), but here I reproduce it and make it easy observable. (although this would be compiler dependent)
If you toggle optimization, you can see output changes and no warning is ever given.
just in case, here is the test code
#include<string>
#include<iostream>
using namespace std;
// No Error
auto& f(const string & s){return s;}
int main()
{
char s[]="#";
const char* cs = s;
auto& x = f(cs);
s[0]='o';
[[maybe_unused]] auto& y = f(cs);
cout << x;
}
g++7.2 -Wall -Wextra -std=c++17
Upvotes: 0
Reputation: 172924
The point is object life time.
For the 1st case, as you said, a temporary std::string
is created and passed to version2
(being bound to the parameter s2
). The temporary will be destroyed after the full-expression, i.e. the whole result = version2(input, "###");
. That means the reference returned by version2
remains valid, it's fine to use it for assigning to result
.
All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created,
For the 2nd case, a local object temp
is created inside version3
, it will be destroyed when get out of version3
. That means version3
will always return a dangled reference. And using it to assign to result
leads to UB. The compiler might give a diagnosis for it; but doesn't have to do.
Upvotes: 3
Reputation: 1486
Both versions return a reference to an object.
version2
got a reference from main and return it unmodified back.
version3
defines a local variable temp
and want to return a reference to this local. But unfortunately the local does no longer exist as soon as you returned from version3
. Thus you would return a reference which would have already been destroyed.
Upvotes: 0