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
_memor 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_wrappers, 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