I tried to find the answer on SO but failed. Sorry if this is a duplicate. I will close the question then.
Could you explain the difference between:
constexpr const char Str1[] = "qwerty";
constexpr auto Str1Size = sizeof(Str1) - 1;
and
constexpr std::string_view Str2{"qwerty"};
constexpr auto Str2Size = Str2.size();
I saw the second variant today and failed to understand. AFAIU std::string_view is a dynamic object, so memory will be dynamically allocated. So how can be this constexpr?
Also, if these variants are really both okay, i.e. are compile-time, then what is their difference? AFAIK, Str2 will not have '\0' and the end of it. Is it all?
std::string_viewis not dynamically allocated. It is essentially aconst char*to the character data and the string length, combined into one object. This can obviously beconstexpr. You might be thinking ofstd::string, which is dynamically allocated.Note that
... is valid, since
"qwerty"is not dynamically allocated but has static storage duration.strpoints to this string literal. If you wrap this in astd::string_view, thestrpointer gets copied. None of this involves dynamic allocation.The null terminator is the only significant difference.
std::string_viewis not guaranteed to be null-terminated, so you lose safe access(1) to it when wrapping the character data in astd::string_view.std::string_viewis also a standard library container, and has an interface which is much nicer to work with. You can create substrings with.substr, etc.(1) Specifically, the null terminator is still contained in the string data, which can be accessed with
.data(). However, an arbitrarystd::string_viewmay not be null-terminated, making it unsafe and bug-prone to rely on it being null-terminated. There is also no safe way to check whether astd::string_viewis null-terminated at run-time, so either you (blindly) believe it, or you assume that it isn't.