3

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?

8
  • 7
    std::string_view does not allocate any memory. It's only a view, it stores a pointer and number of characters. Commented Oct 25, 2023 at 9:04
  • 1
    std::string_view is just fancy form of const reference to a string. In case of costexpr it is const reference to a string literal. Commented Oct 25, 2023 at 9:05
  • 3
    "std::string_view is a dynamic object, so memory will be dynamically allocated", No, its not. std::string will alocate memory, but std::string_view will only hold pointer to the external data Commented Oct 25, 2023 at 9:05
  • 2
    It only lacks \0 if the string it points to lacks it. std::string_view is effectively just a struct with a const char *ptr; std::size_t size; in it. Commented Oct 25, 2023 at 9:07
  • 2
    @JenyaKh obviosly, it is. "qwerty" Is array of 7 const chars, not 6. Commented Oct 25, 2023 at 9:16

1 Answer 1

3

AFAIU std::string_view is a dynamic object, so memory will be dynamically allocated. So how can be this constexpr?

std::string_view is not dynamically allocated. It is essentially a const char* to the character data and the string length, combined into one object. This can obviously be constexpr. You might be thinking of std::string, which is dynamically allocated.

Note that

constexpr const char* str = "qwerty";

... is valid, since "qwerty" is not dynamically allocated but has static storage duration. str points to this string literal. If you wrap this in a std::string_view, the str pointer gets copied. None of this involves dynamic allocation.

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?

The null terminator is the only significant difference. std::string_view is not guaranteed to be null-terminated, so you lose safe access(1) to it when wrapping the character data in a std::string_view. std::string_view is 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 arbitrary std::string_view may 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 a std::string_view is null-terminated at run-time, so either you (blindly) believe it, or you assume that it isn't.

Sign up to request clarification or add additional context in comments.

1 Comment

But you already have size as the number of reliable characters. So in case you need to interface C API, you can use the n infixed versions(` strndup instead of strdup...). All that null served was to mark the end of string, now you get it with size. Unless size is explicitly fed to ctor, or array(or std::array, std::vector) is used as initializer, the null character is still at the tail. By wrapping/boxing string_view, you can constrain it to either category of null or none-null terminated strings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.