Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return reference to temporary when dereferencing map iterator

Consider this code

#include <iterator>
#include <vector>

const int& foo(const std::vector<int>& x,unsigned i) {
    auto it = x.begin();
    std::advance(it,i);
    return *it;
}

Both clang and gcc emit no errors/warnings, but this:

#include <iterator>
#include <map>

const std::pair<int,int>& bar(const std::map<int,int>& x,unsigned i){
    auto it = x.begin();
    std::advance(it,i);
    return *it;
}

compiled with clang and using -Werror results in :

<source>:14:12: error: returning reference to local temporary object [-Werror,-Wreturn-stack-address]
    return *it;
           ^~~

and with gcc:

<source>: In function 'const std::pair<int, int>& bar(const std::map<int, int>&, unsigned int)':
<source>:14:13: error: returning reference to temporary [-Werror=return-local-addr]
     return *it;
             ^~

What makes gcc and clang reject bar and why is foo fine?

like image 638
463035818_is_not_a_number Avatar asked Mar 24 '18 08:03

463035818_is_not_a_number


1 Answers

The problem is that the value_type of std::map<int,int> is not std::pair<int,int>, but std::pair<const int,int>. Then for return *it;, a temporary std::pair<int,int> has to be created and returned. (std::pair<int,int> could be converted from std::pair<const int,int>.) The temporary will be destroyed immediately and left the returned reference dangled.

To sovle the issue you can change the return type to const std::pair<const int,int>& or const std::map<int,int>::value_type &.

like image 98
songyuanyao Avatar answered Sep 28 '22 08:09

songyuanyao