#031 – std::string_view: A Lightweight String Reference

Consider this program

class Character
{
	public:
    virtual std::string GetClassName() const = 0;
};

class Warrior : public Character
{
    std::string GetClassName() const override { return "Warrior"; }
};

Here’s what happens

  1. "Warrior" is stored as a C-style literal.
  2. When the method is called, a new std::string is constructed from the C-style literal
  3. std::string is deleted via its destructor
  4. Repeat for however many times this method is called (which is a lot btw)

This is additional overhead for simply getting a string. This is inefficient.

Fortunately, we can do better.

Since we don’t modify the string, this is a good justification to use std::string_view.

Introducing std::string_view (C++17)

std::string_view provides read-only access to a:

  1. C-style string literal
  2. std::string
  3. std::string_view (itself!)

Let’s refactor the above program using std::string_view

class Character
{
	public:
    virtual std::string_view GetClassName() const = 0;
};

class Warrior : public Character
{
    std::string_view GetClassName() const override { return "Warrior"; }
}

Did you notice the change?

A word of caution

std::string gets implicitly converted into std::string_view however, the reverse doesn’t apply.

A std::string_view does not implicitly convert back into a std::string.

Consider the following

#include <iostream>

// Accepts std::string
void print(std::string str) {
    std::cout << str;
}

int main() {
    std::string_view c1 = "Hello";
    print(c1);
}

// Output
error: could not convert 'c1' from 'std::string_view'

There are 2 solutions

  1. Construct a std::string from the std::string_view and pass that in
  2. Apply static_cast<>
// Applying solution 1
std::string d1 { c1 };
print(d1);

// Applying solution 2
print(static_cast<std::string>(c1));

NOTE: std::string_view does not implicitly convert into std::string

std::string_view provides read-only access

Consider this program,

#include <string>
#include <string_view>

std::string_view getName()
{
    std::string name { "New York Yankees" };

    return name; // Return std::string
}

The function creates and returns a temporary std::string. When the function goes out of scope, std::string_view is looking at invalid data. A dangling view has been created.

However, returning a view to a C-style string literal is safe, as seen in GetClassName() above.

NOTE: If the string that std::string_view is viewing changes then std::string_view becomes obsolete. This results in a dangling view

Advantage of std::string_view

It supports constexpr. This allows us to perform compile-time programming which is a massive plus!

E.g. constexpr std::string_view s{ "Hello beautiful world!" };

NOTE: std::string gained constexpr support as of C++20

Takeaway

std::string_view is not a direct replacement for std::string. They each serve their own purposes.

Use std::string when you need to own or modify the text.

Use std::string_view when you only need to read text owned by something else.

Leave a Reply

Your email address will not be published. Required fields are marked *