Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams int main(int argc, char* argv[]) { std::unordered_map<std::string, int> m = { {"asdf", 123}, {"dsdfesjfdaslkfjasljlasfjlasjfakdlsfjasklfajsklfjaskljlf", 123}, {"ldfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, {"ldafjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, {"ldjaksdfjfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, {"ldfjaslk}sfdasfdsfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, {"ldfjaslk}sfjalsksfdasdfdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, {"ldfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1}, std::vector<std::pair<std::string_view, int>> vec; for (auto& [s, i] : m) { vec.push_back(std::make_pair(s, i)); std::cout << vec.back().first << std::endl;

Basically, vector is created with the element of the map. The thing is that it instead converts the string to string_view when inserting to the vector. I thought this would be okay as we are using const string reference to construct string_view, and the string will be available throughout the lifespan of the vector.

But when I checked the output, it showed seemingly corrupted data.

�/�U.�Usfdasdfdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
�/�U.�Usfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
@/�U.�Ukdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
�/�U.�Usfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
@/�U.�Udfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
.�Usljlasfjlasjfakdlsfjasklfajsklfjaskljlf

I guess string_view in the vector no longer points to the proper element. But why this has happend? I assumed that the unordered_map would be immutable while iterating so the address of the key element would not have changed.

Godbolt link : https://godbolt.org/z/dePdv5

Wouldn't std::make_pair make a copy of the string, and then vec store a reference to the copy? – spectras Dec 20, 2020 at 12:22 ahhh. So when I fixed it to vec.push_back(std::make_pair(std::string_view(s), i));, it fixed it. But I wonder how would this not be a default behavior? – Jaebum Dec 20, 2020 at 12:24

Using make_pair you generate a temporary object of type std::pair<std::string, int>. I would expect the conversion to std::pair<std::string_view, int> to throw an error, but apparently it works.

Anyhow, std::string_view is non-owning, so as soon as the temporary object is destroyed (at the end of the line ;) it becomes dangling.

You shouldn't make a new pair. Try emplace_back with the key and value.

cool. I have been told to avoid emplace_back as it might call the unexpected ctor. But I guess this is the only case I find it useful :P – Jaebum Dec 20, 2020 at 12:28 The conversion exists because std::string to std::string_view is an implicit conversion. You kinda see why people were "upset" about that decision. – Passer By Dec 20, 2020 at 12:35

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.