The string_view family of template specializations provides an efficient way to pass a read-only, exception-safe, non-owning handle to the character data of any string-like objects with the first element of the sequence at position zero.
#include <iostream>
#include <string_view>
#include <unordered_map>
using namespace std;
std::unordered_map<std::string_view, int> create_map()
{
std::unordered_map<std::string_view, int> umap;
std::string s1("s1");
auto s2_bad = new std::string("s2");
umap.emplace(std::make_pair(s1, 1)); // doesn't work b/c sv points to local variable
umap.emplace(std::make_pair(*s2_bad, 2)); // Q1> why doesn't this work?
umap.emplace(std::make_pair("s3", 3)); // Q2> why does this work?
auto s4_bad = new std::string("s4_bad");
umap.emplace(std::make_pair(s4_bad->c_str(), 4)); // this works
return umap;
}
int main()
{
auto abc_map = create_map();
for(const auto&[key, value]: abc_map)
{
std::cout << "key: " << key << std::endl;
std::cout << "value: " << value << std::endl;
}
return 0;
}
Output:
key: s3
value: 3
key: $
value: 2
key: s4_bad
value: 4
key: $
value: 1
Question 1> Why doesn't s2_bad
work here? Even if it points to an allocated address space.
Question 2> Why does the insertion of string literal "s3" work here? Even if it is defined within a scope of a function?
CodePudding user response:
Question 1: std::make_pair(*s2_bad, 2)
will create a std::pair<std::string, int>
, so the pair has a distinct temporary std::string
, unrelated to the string s2_bad
points to. Then, a std::string_view
will be constructed from this temporary, which will be promptly destroyed. So the moment umap.emplace(std::make_pair(*s2_bad, 2));
finishes, the string_view
is invalid. If you'd like to avoid this copy (and the associated lifetime problems), you can use std::ref(*s2_bad)
instead of *s2_bad
.
Question 2: String literals have static
lifetimes, i.e. their contents are stored in the read-only sections of binaries instead of in the stack, so holding a pointer to a string literal and returning from the function containing the string literal does not pose any dangling pointer problems.