C++

String View in C++

In the domain of C++ programming, prioritizing efficiency and performance is crucial. The “std::string_view” class, introduced in C++17, presents a versatile and memory-efficient alternative to traditional string manipulation.  At its core, “std::string_view” is a non-owning reference to a sequence of characters, commonly representing a substring of a larger string. Unlike “std::string” which owns its data and manages the memory internally, “std::string_view” operates without owning the underlying data. This characteristic makes it particularly valuable for scenarios where the overhead of copying or managing the memory is undesirable. In this article, we will explore the different examples to comprehend the utilization of “std::string_view” in C++.

Example 1: Efficient String Handling

In modern C++ development, efficient string handling is crucial for optimizing the performance and resource utilization. It allows an efficient access and manipulation of strings without needing the memory reallocation or duplication. To illustrate this concept, let’s delve into a practical example.

Consider the following code snippet:

#include <iostream>
#include <string_view>

void processStringView(std::string_view strView) {

    std::cout << "Length: " << strView.length() << std::endl;
    std::cout << "Content: " << strView << std::endl;
}

int main() {
   
    std::string originalString = "Efficient String Handling";

    std::string_view viewOfString(originalString);

    processStringView(viewOfString);

    return 0;
}

 
In this example, we have the “processStringView” function that takes “std::string_view” as its parameter. The function then prints the length and content of the string view using the standard output. The main function initializes the “std::string” named “originalString” with the “Efficient String Handling” value. Subsequently, the “std::string_view” named ‘viewOfString” is created, referring to the content of “originalString”.

By passing the “viewOfString” to the “processStringView” function, we can perform the operations on the string efficiently, eliminating the necessity for extra memory allocations. The “std::string_view” is a lightweight reference to the underlying character sequence of “originalString” without copying the data.

Here is the generated output:

Example 2: Interoperability with Legacy Code

In the realm of C++ development, the seamless integration of new and old codebases is often a critical concern. The “std::string_view” allows the developers to interact effortlessly with legacy functions that return the “const char” pointers.

Consider the following example that demonstrates the practical use of “std::string_view” for interoperability. Here, we have a legacy function named “legacyFunction()” that returns a “const char” pointer:

#include <iostream>
#include <string_view>

const char* legacyFunction() {
    return "Legacy String";
}

int main() {
   
    std::string_view legacyStrView(legacyFunction());

    std::cout << "Legacy String View: " << legacyStrView << std::endl;

    return 0;
}

 
We begin by defining a legacy function named “legacyFunction()” which returns a “const char” pointer that represents a string that is labeled as “Legacy String”. To seamlessly incorporate this legacy data into our modern C++ program, we employ the “std::string_view”. In the main() function, specifically, we create an instance of “std::string_view” named “legacyStrView” and initialize it with the result of the legacy function. This instantiation allows us to efficiently encapsulate and work with the legacy “const char” pointer.

As a result, we can access and manipulate the legacy string without resorting to unnecessary data copying, preserving both efficiency and compatibility. The final step in the code involves utilizing the “std::cout” to print the content of the legacy string view.

The executed output is:

Example 3: Improved String Literals Handling

String literals in C++ are traditionally represented as arrays of characters. The “std::string_view” simplifies working with string literals by providing a convenient interface. By allowing a direct access to the underlying character array without the need for explicit conversions, “std::string_view” streamlines the operations on string literals.

#include <iostream>
#include <string_view>

int main() {
    const char* myLiteral = "Hello, String View!";
    std::string_view literalView(myLiteral);

    std::cout << "First character: " << literalView[0] << std::endl;

    size_t position = literalView.find("String");
    std::cout << "Substring position: " << position << std::endl;

    return 0;
}

 
In this example, a “Hello, String View!” string literal is assigned to the “myLiteral” pointer. The introduction of “std::string_view” facilitates a more efficient representation of this string without the need to copy its contents. The “literalView” object is created using the “myLiteral” pointer which allows us to view and manipulate the underlying character sequence.

The usage of “std::string_view” provides an easy access to individual characters within the string. In the code snippet, “literalView[0]” retrieves and prints the string’s first character, showcasing the simplicity and directness of accessing the elements. The “find” method of “std::string_view” is employed to determine the position of the “String” substring within the original string.

Example 4: Substring Extraction

The task of substring extraction involves retrieving a portion of a given string based on specified criteria such as the position of a delimiter. The ability to effortlessly extract the substrings is a powerful feature of “std::string_view”. Consider a scenario where we need to extract a portion of a string based on a delimiter:

#include <iostream>
#include <string_view>

int main() {
    std::string fullString = "apple-orange-banana";
    size_t delimiterPos = fullString.find('-');

    std::string_view subString = fullString.substr(0, delimiterPos);

    std::cout << "Extracted Substring: " << subString << std::endl;

    return 0;
}

 
In this code snippet, we begin with the declaration of an original string, “fullString”, which is initialized with the “apple-orange-banana” value. Our goal is to perform the substring extraction. To achieve this, we employ the “find” function provided by the C++ standard library.

Once we identify the position of the delimiter within the “fullString”, stored in the “delimiterPos” variable, we extract the desired substring. The “substr” function is called on the original string, specifying the starting position (0) and the length of the substring which is precisely the position of the delimiter. This operation results in the creation of the “std::string_view” named “subString” that represents the portion of the original string from the beginning up to the delimiter.

Example 5: Memory-Efficient Data Structures

The “std::string_view” plays a crucial role in designing the memory-efficient data structures. Instead of storing multiple copies of strings, data structures can store the “std::string_view” instances, thus reducing the memory overhead.

#include <iostream>
#include <string_view>

struct Record {
    std::string_view name;
    int age;
};

int main() {
   
    Record person = { "John Doe", 30 };

    std::cout << "Name: " << person.name << ", Age: " << person.age << std::endl;

    return 0;
}

 
In this code snippet, we showcase the utilization of “std::string_view” within a memory-efficient data structure. We define a “Record” structure that comprises an “std::string_view” member named “name” and an integer member called “age”. The use of “std::string_view” in this context allows us to create a lightweight representation of a string without the need for additional memory allocation.

In the “main” function, we instantiate a “Record” object named “person” with the name “John Doe” and the age of 30. The “std::string_view” member “name” serves as a non-owning view of the character data corresponding to the name, eliminating the necessity for duplicating the string content. The “std::cout << “Name: ” << person.name << “, Age: ” << person.age << std::endl;” statement outputs the name and age of the person which are stored in the “Record” object.

Conclusion

In the ever-evolving landscape of the C++ development, “std::string_view” stands out as a valuable addition to the programmer’s toolkit. The instances that are illustrated in this article highlight the adaptability and utility of “std::string_view” within the realm of C++ programming. From efficient string manipulation and seamless interoperability with legacy code to memory-efficient data structures, “std::string_view” is valuable for developers who are seeking for enhanced performance and optimized code in diverse scenarios. These real-world scenarios demonstrate how “std::string_view” can optimize the code, reduce unnecessary memory overhead, and contribute to the overall efficiency of C++ applications.

About the author

Kalsoom Bibi

Hello, I am a freelance writer and usually write for Linux and other technology related content