Search code examples
c++visual-studioconst-reference

Is using rvalue reference to erased element of STL container undefined behavior?


Part of my program does something like this:

#include <unordered_set>
#include <unordered_map>

std::unordered_map<std::string, int> G{{"1", 10}};

int m(const std::string& i, std::unordered_set<std::string>& v) {
    v.erase(i);
    return G.at(i);
}

int main() {
    std::unordered_set<std::string> v {"1"};
    const std::string& remove_this = *v.begin();
    return m(remove_this, v);
}

The program should be portable between linux and windows. When compiled with g++, the program runs well and returns 10, as expected. However, when compiled with VS 2017, the programs aborts, throwing an std::out_of_range. With most trivial effort of debugging, I see that i in function m is destroyed before the call to G.at. (both without optimizations)

To my understanding, the const reference to v.begin() should expire until m returns (the g++ case). But it MSVC obviously didn't agree with that.

Is this undefined behavior or implementation defined? When, indeed, does an argument passed by const reference expire then?


Solution

  • The argument i lives until m ends. However, the object that i references disappears after v.erase(i), leaving i as a dangling reference. G.at(i) then reads from the dangling reference causing undefined behavior.