I want to convert std::uint16_t
to std::string_view
. I was expecting the following code would work:
std::string_view to_str(std::uint16_t v) {
return std::string_view(std::to_string(v));
}
because it uses an intermediary std::string
in to_str
function scope.
I know I can use a static storage for intermediary string like this:
std::string_view to_str(std::uint16_t v) {
static auto str = std::to_string(v);
return std::string_view(str);
}
I know there is another way to use char buffer
and convert it to string_view
but I wonder is there any better way to serve this very same purpose? Is it even logical to return string_view
instead of string
?
The problem is that std::string_view
is a lightweight class that does not own the data. It is marely a view into the data held by another object (e.g. a std::string
). And you need the object holding the data to be alive as long as you intend to use the string_view
.
In this line:
return std::string_view(std::to_string(v));
You return a string_view
referring a temporary std::string
returned from std::to_string
. This temporary is then destroyed and therefore the string_view
that you return is invalid (similarly to a dangling pointer/reference). Accessing it invokes undefined-behavior.
When you use static auto str = std::to_string(v);
it seems to solve this problem because the static str
will stay alive after the function returns. But in fact it is not a good solution. str
will only be initialize once and so the next call to to_str
with a different value for v
will still return a string_view
for the first call.
The solution is to simply return a std::string
instead of a std::string_view
(returning a string_view
does not make sense because of the reason explained above).
You will still be able to pass it to methods that expect a std::string_view
.