C++17: std::string_view

If you have to write a function that accepts a string, what type of parameter will you use? You have a couple of choices:

  • const std::string&: downside is that whenever you call the function, an std::string is expected. If you pass a const char*, an std::string instance will be created implicitly for you.
  • const char*: downside is that if your caller has an std::string, they will have to use c_str() on it to pass a const char* to your function.
  • A const char* overload and a const std::string& overload: downside is that you have to implement two functions. This solution quickly becomes unwieldy if you are writing a method that accepts more than one string as parameter. For example, suppose your method requires two strings as parameters. If you want to overload the method to provide all possible combinations of input argument types, then you end up writing four versions: (const char*, const char*), (const char*, const string&), (const string&, const char*), and (const string&, const string&). This only becomes worse with even more string parameters.

C++17 makes it easy by introducing a new type called std::string_view. From now on, if you are writing a function that accepts a string, use an std::string_view as parameter type. No need to use an std::string_view reference. A string_view is very cheap to copy, so it’s perfectly fine to pass by value. Basically, a string_view just contains a pointer to a string, and its length. A string_view parameter accepts any kind of string, such as a C++ std::string, a C-style const char* string, and a string literal, all without any copying involved!

std::string_view is defined in the <string_view> header. It has a similar interface as the well-known std::string class. However, since a string_view is a read-only view of a string, only the const operations of std::string are supported on a string_view. Additionally, a big advantage of a string_view is that it will never copy a string.

Here is a very brief example of its usage:

#include <iostream>
#include <string_view>

using namespace std;

void ProcessString(string_view myString)
{
    cout << myString; if (myString.size() >= 4)
    {
        cout << "   (Substring: " << myString.substr(2, 2) << ")";
    }
    cout << endl;
}

int main()
{
    string myString1 = "Hello";
    const char* myString2 = "C++";
    ProcessString(myString1);  // C++ string
    ProcessString(myString2);  // C-style string
    ProcessString("World!");   // String literal
}

The output of this piece of code is as follows:

Hello   (Substring: ll)
C++
World!   (Substring: rl)

My book, Professional C++, 4th Edition, explains the std::string_view class in a bit more details. Additionally, it explains all new C++17 features, and much more.

Share

3 Comments so far »

  1. Olivier Galibert said,

    Wrote on June 8, 2018 @ 8:44 pm

    Is that pointer/size 16 bytes combo significantly better than a 24-32 bytes SSO-ed string to we worth adding an indirection on access?

    OG.

  2. Marc Gregoire said,

    Wrote on June 9, 2018 @ 2:54 am

    Olivier: Maybe not, maybe yes. If performance is so critical for you that you start looking at the impact of an extra indirection, then you should really use a profiler and verify which is best for your specific use case.

  3. Mario said,

    Wrote on June 9, 2018 @ 1:44 pm

    Why would there be an extra level of indirection?

Comment RSS · TrackBack URI

Leave a Comment

Name: (Required)

E-mail: (Required)

Website:

Comment: