Given an object like this one:
struct Foo {
string _mem;
pair<bool, const string&> Func() { return make_pair(true, _mem); }
};
Am I actually returning a reference to _mem
or not? My understanding was that in c++14 make_pair
would forward my type allowing the return I'm using to capture it as a reference to the object's _mem
.
This behavior seems consistent with what I'm seeing in gcc 8: http://ideone.com/adz17e But when I try to run this on visual-studio-2017 it seg-faults. If I change to return make_pair(true, ref(_mem))
it works, but I didn't think that I needed to. Which one of these behaviors is correct?
Am I actually returning a reference to
_mem
or not?
No, you are not. make_pair(true, _mem)
is a std::pair<bool, std::string>
that is a copy of that your member. It's then converted to a std::pair<bool, std::string const&>
in the return type which means you're returning a reference to a temporary which is immediately destroyed. Unconditional dangling.
Recall that C++ is a value semantics language. Nothing is a reference by default, you have to be explicit about this.
You have two ways of doing this. You can either mark that you want a reference:
return std::make_pair(true, std::ref(_mem));
make_pair
will unwrap std::reference_wrapper
s, so this expression is a std::pair<bool, std::string&>
.
Or, you can just be explicit:
return std::pair<bool, std::string const&>(true, _mem);
Which you can write shorter as:
return {true, _mem};
It is undefined behaviour.
Since c++11 make_pair is defined as:
template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );
In your case _mem
is Lvalue, so T2
is deduced to be string&
, but V2
of result pair is deduced from std::decay(string&)
. std::decay
always discards reference. Returned pair has dangling reference in second
member.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With