Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I Need to use ref With make_pair to Return a Reference?

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?

like image 964
Jonathan Mee Avatar asked Sep 09 '19 19:09

Jonathan Mee


2 Answers

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_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};
like image 53
Barry Avatar answered Oct 31 '22 02:10

Barry


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.

like image 32
rafix07 Avatar answered Oct 31 '22 02:10

rafix07