6.6a — An introduction to std::string_view

In the previous lesson, we talked about C-style strings, and the dangers of using them. C-style strings are fast, but they’re not as easy to use and as safe as std::string.

But std::string (which we covered in lesson S.4.4b -- An introduction to std::string), has some of its own downsides, particularly when it comes to const strings.

Consider the following example:

As expected, this prints

hello hello hello

Internally, main copies the string “hello” 3 times, resulting in 4 copies. First, there is the string literal “hello”, which is known at compile-time and stored in the binary. One copy is created when we create the char[]. The following two std::string objects create one copy of the string each. Because std::string is designed to be modifiable, each std::string must contain its own copy of the string, so that a given std::string can be modified without affecting any other std::string object.

This holds true for const std::string, even though they can’t be modified.

Introducing std::string_view

Consider a window in your house, looking at a car sitting on the street. You can look through the window and see the car, but you can’t touch or move the car. Your window just provides a view to the car, which is a completely separate object.

C++17 introduces another way of using strings, std::string_view, which lives in the <string_view> header.

Unlike std::string, which keeps its own copy of the string, std::string_view provides a view of a string that is defined elsewhere.

We can re-write the above code to use std::string_view by replacing every std::string with std::string_view.

The output is the same, but no more copies of the string “hello” are created. When we copy a std::string_view, the new std::string_view observes the same string as the copied-from std::string_view is observing.
std::string_view is not only fast, but has many of the functions that we know from std::string.

Because std::string_view doesn’t create a copy of the string, if we change the viewed string, the changes are reflected in the std::string_view.

We modified arr, but str appears to be changing as well. That’s because arr and str share their string. When you use a std::string_view, it’s best to avoid modifications to the underlying string for the remainder of the std::string_view‘s life to prevent confusion and errors.

Best practice

Use std::string_view instead of C-style strings.

Prefer std::string_view over std::string for read-only strings, unless you already have a std::string.

View modification functions

Back to our window analogy, consider a window with curtains. We can close either the left or right curtain to reduce what we can see. We don’t change what’s outside, we just reduce the visible area.

Similarly, std::string_view contains functions that let us manipulate the view of the string. This allows us to change the view without modifying the viewed string.

The functions for this are remove_prefix, which removes characters from the left side of the view, and remove_suffix, which removes characters from the right side of the view.

This program produces the following output:


Unlike real curtains, a std::string_view cannot be opened back up. Once you change the visible area, you can’t go back (There are tricks which we won’t go into).

std::string_view works with non-null-terminated strings

Unlike C-style strings and std::string, std::string_view doesn’t use null terminators to mark the end of the string. Rather, it knows where the string ends because it keeps track of its length.

This program prints:


Ownership issues

Being only a view, a std::string_view‘s lifetime is independent of that of the string it is viewing. If the viewed string goes out of scope, std::string_view has nothing to observe and accessing it causes undefined behavior.

What's your name?
Hello nascardriver
Your name is �P@�P@

When we created str and filled it with std::cin, it created its internal string in dynamic memory. When str goes out of scope at the end of askForName, the internal string dies along with str. The std::string_view doesn’t know that the string no longer exists and allows us to access it. Accessing the released string through view in main causes undefined behavior, which on the author’s machine produced weird characters.

The same can happen when we create a std::string_view from a std::string and modify the std::string. Modifying a std::string can cause its internal string to die and be replaced with a new one in a different place. The std::string_view will still look at where the old string was, but it’s not there anymore.


Make sure that the underlying string viewed with a std::string_view does not go out of scope and isn’t modified while using the std::string_view.

Converting a std::string_view to a std::string

An std::string_view will not implicitly convert to a std::string, but can be explicitly converted:

This prints:


Converting a std::string_view to a C-style string

Some old functions (such as the old strlen function) still expect C-style strings. To convert a std::string_view to a C-style string, we can do so by first converting to a std::string:

This prints:

ball has 4 letter(s)

However, creating a std::string every time we want to pass a std::string_view as a C-style string is expensive, so this should be avoided if possible.

Opening the window (kinda) via the data() function

The string being viewed by a std::string_view can be accessed by using the data() function, which returns a C-style string. This provides fast access to the string being viewed (as a C-string). But it should also only be used if the std::string_view‘s view hasn’t been modified (e.g. by remove_prefix or remove_suffix) and the string being viewed is null-terminated.

In the following example, std::strlen doesn’t know what a std::string_view is, so we need to pass it


When a std::string_view has been modified, data() doesn’t always do what we’d like it to. The following example demonstrates what happens when we access data() after modifying the view:

all has 6 letter(s) is alloon
str is all

Clearly this isn’t what we’d intended, and is a consequence of trying to access the data() of a std::string_view that has been modified. The length information about the string is lost when we access data(). std::strlen and std::cout keep reading characters from the underlying string until they find the null-terminator, which is at the end of “balloon”.


Only use std::string_view::data() if the std::string_view‘s view hasn’t been modified and the string being viewed is null-terminated. Using std::string_view::data() of a non-null-terminated string can cause undefined behavior.

Incomplete implementation

Being a relatively recent feature, std::string_view isn’t implemented as well as it could be.

There’s no reason why line 5 and 6 shouldn’t work. They will probably be supported in a future C++ version.

6.7 -- Introduction to pointers
6.6 -- C-style strings

37 comments to 6.6a — An introduction to std::string_view

  • Don

    So ...
    1. When modifying a C-style string, the std::string_view which is observing that string will get the changes too.
    2. But when modifying a std::string, the observing std::string_view will somehow causes undefined behavior.
    3. So it is the best to use std::string_view only to observe literal strings.
    Do I understand correctly ?

  • Jimmy Hunter

    I'm a little confused.  The following two teaching points seem to contradict each other on the subject of std::string_view and whether it is a null-terminated string. Can you help please?

    Unlike C-style strings and std::string, std::string_view doesn’t use null terminators to mark the end of the string. Rather, it knows where the string ends because it keeps track of its length.

      // It's okay to use data() because we haven't modified the view, and the
      // string is null-terminated.
      std::cout << std::strlen( << '\n';

    Did you mean to write in the commented line that "string is not null-terminated"?

    • nascardriver

      Nope, it's correct as written. Not every `std::string_view` views a null-terminated string. `std::string_view` doesn't modify the string it's viewing. If we initialize it with a string literal (Remember that string literals are null-terminated), then we can safely access `data()`, because it's just a view at out string literal (Which is null-terminated). Though, we have to keep track of this ourselves. If we initialized the `std::string_view` with a char array or let it view only a section of a string, it would not be null-terminated.

  • Bruno

    >>Being only a view, a std::string_view‘s lifetime is independent of that of the string it is viewing. If the viewed string goes out of scope, std::string_view has nothing to observe and accessing it causes undefined behavior.

    Dependent instead of independent ?

    • Alex

      A std::string_view has an independent lifetime from the string it's viewing (e.g. a std::string_view can outlive the string it's viewing, at which point, it becomes invalid).
      A std::string_view validity is dependent on the string it's viewing (e.g. a std::string_view becomes invalid when the string it's viewing dies).

  • Jordy

    std::string_view's function seems to overlap a lot with what constant references are used for. Why is it preferred?

    • nascardriver

      I suppose you mean a const reference to a `std::string`.
      `std::string` can't be used at compile-time, as it requires dynamic memory allocation. Also, if you use a `std::string`, you have to create it first before you can bind a reference to it. Creating the `std::string` creates a copy of the string literal, which might be undesired.

  • kitabski

    Good day everybody!!!
    Wanted to clarify one thing.
    The following code works just fine even though i don't include string or string_view

  • kavin

    Hi,  Under Opening the window (kinda) via the data() function:
    how do we know  std::string_view str{ "balloon" }; is null-terninated string?

    From what i understood is it because all strings(refers to group of characters here) default to null-terminated strings? If the characters are separated by "," they naturally default to non-null-terminated and c-style, which can only be printed to screen by converting them to std::string_view like in vowels example ? Is it correct ?

    • nascardriver

      "balloon" is a string literal, string literals are zero-terminated. If you have an array of characters, then that array isn't zero-terminated (unless you added a terminator).

      • kavin

        Thank you, we add an terminator to array of characters like this right??

        Here it prints 0 after aeiou but its not shown in output right ?

        • nascardriver

          Right. When you print a 0-valued byte, you see nothing. You could print the array without a loop, because now `std::cout` can know where the string ends.

          • giang

            Then, can I ask a C-style string, and string literals are null-terminated, whether string or string_view's variable are not???

            • nascardriver

              It doesn't matter if `std::string` is zero-terminated. The only way to access its internal string is via `.data()` and `.c_str()`, both of which are guaranteed to return a zero-terminated string.
              `std::string_view` is not zero-terminated, because it's just a view onto another string. It has no influence on the string's data, so the only way to reliably know where the string ends is by storing the string's length. This allows `std::string_view` to shrink the viewed string without modifying it (It simply reduces the length).

  • chai

    char arr[]{ "Gold" };
    char name[] = "Jason";

    I learned in lesson 6.8 that I haven't got '\0' at the end of "Gold" but got one with "Jason". Is the assignment initialisation better?

    • nascardriver

      Both arrays are zero-terminated


      Lesson 6.6 says so. I couldn't find anything stating the opposite in lesson 6.8. If there's misinformation in lesson 6.8, please point it out as to not confuse other readers.

  • BakaTensi

    So basically, std::string_view is kinda incomplete, and should only be used when we need constant strings at this point if I understand correctly?

  • Vuk

    Hi, I think there is a missing parenthesis in the third code example for the substr call.

  • Wallace

    Minor typo: In "When you use a std::string_view, it’s best to avoid modifications the to underlying string," "the" and "to" seem swapped.

  • Fan

    OK. I saw that the first example has been modified to use char[] instead of const char *, but then should there also be a copy of the string allocated on the stack frame of main()?

    • nascardriver

      Right, I missed that when updating the lesson to use `char[]`, thanks for pointing it out!.

      • Fan

        Then it comes up to 4 copies of the string?

        • nascardriver

          I don't think so. When you have 1 paper and copy it, you have 2 papers but only 1 copy, right?
          The string is there 4 times, but only 3 of the strings are copies. That's how I look at it, I don't know if it's correct.

          • Alex

            In C++, the term "copies" is often used to mean the "number of" something. So if you have a string, and you copy it, you now have two copies of that string.

            I think it's more correct to say that the first program has 4 copies of the string -- but function main only creates 3 of those copies. Perhaps the text should be amended to say, "main creates 3 copies" rather than "this program creates 3 copies"? That way we avoid the ambiguity about whether the string in read-only memory counts as a "copy" or not.

  • Omar Abdelazeem

    when I'm trying to compile this code , the compiler complain that
    'string_view': is not a member of 'std'


    #include <iostream>
    #include <string_view>

    int main()
        std::string_view text{ "hello" }; // view the text "hello", which is stored in the binary
        std::string_view str{ text }; // view of the same "hello"
        std::string_view more{ str }; // view of the same "hello"

        std::cout << text << ' ' << str << ' ' << more << '\n';

        return 0;


  • ErwanDL

    Hey nascardriver,

    From the start of this article, you introduce "const char*" to define strings but I don't think we have already seen what it is and what it does earlier in the tutorial. Is it like using "std::string" ?

    Another thing is I have played around a bit with std::string_view and there are some pretty bizarre behaviours, like in the following code :

    This prints :

    Hello Hello
    Hi Hilo

    What is happening here ? Maybe this could be explained in the article as well ?


    • ErwanDL

      Update : I've advanced to lesson 6.8b and the syntax "const char*" is explained there (C-style string symbolic constants). Maybe this lesson on std::string_view should be moved further down the chapter ?

    • nascardriver

      > you introduce "const char*" to define strings but I don't think we have already seen what it is
      It's a `const char[]` with a different syntax, I though it was a part of the previous lesson, but it isn't. I changed every `const char*` to `char[]` or "C-style string". Thanks for letting me know!

      > like in the following code
      I wanted to include an example that shows that `std::string_view` reflects the changes made to its underlying string, but I'd have to move this lesson further back, which I don't want to do, because it would motivate the use of C-style strings.
      Your code invokes undefined behavior (I added a paragraph to the lesson).
      When you assign "Hi" to `str` in line 8, `str`'s old string "Hello" can be invalidated. In your case, since "Hi" is shorter than "Hello", the `std::string` re-used the memory it was using the store "Hello". That memory is now "Hi\0lo" (\0 is a null-terminator).
      If you assigned something longer, the old string could die completely.
      `view` still looks at where the old string was, but `view`'s size isn't changed (The curtains are where they were before). Since `std::string_view` doesn't use null-terminators, the \0 is ignored and "Hilo" is printed.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]