Search Knowledge

© 2026 LIBREUNI PROJECT

Modern C++ Programming / Modern C++ Features

String View and Span

Non-Owning Views: Efficient Abstractions

C++17/20 introduced view types that refer to existing data without owning it, avoiding unnecessary copies.

std::string_view (C++17)

Lightweight non-owning reference to a string:

#include <string_view>

void print(std::string_view sv) {  // No copy!
    std::cout << sv << '\\n';
}

std::string str = "hello";
const char* cstr = "world";
print(str);   // OK: string converts to string_view
print(cstr);  // OK: const char* converts to string_view
print("literal");  // OK: no temporary std::string created

Performance Advantage

// Bad: Creates temporary string for each call
void process(const std::string& s);
process("literal");  // Allocates memory!

// Good: No allocation
void process(std::string_view s);
process("literal");  // Just pointer + length

string_view Operations

std::string_view sv = "Hello, World!";

sv.size();     // 13
sv.length();   // 13
sv.empty();    // false
sv.data();     // Pointer to first character

sv[0];         // 'H'
sv.front();    // 'H'
sv.back();     // '!'

sv.substr(7, 5);  // "World"
sv.remove_prefix(7);  // sv = "World!"
sv.remove_suffix(1);  // sv = "World"

Lifetime Hazards

Critical: string_view doesn’t own data—ensure underlying data outlives the view:

std::string_view get_view() {
    std::string temp = "temporary";
    return temp;  // DANGER: Returns view to destroyed string!
}

auto sv = get_view();
std::cout << sv;  // UB: Dangling reference!

Safe usage:

std::string str = "persistent";
std::string_view sv = str;  // OK: str outlives sv

void func(std::string_view sv) {
    // OK: sv only used during function
}

std::span (C++20)

Non-owning view over contiguous sequence:

#include <span>

void process(std::span<int> data) {
    for (int& x : data) {
        x *= 2;
    }
}

std::vector<int> vec = {1, 2, 3, 4, 5};
int arr[] = {1, 2, 3, 4, 5};

process(vec);  // Works with vector
process(arr);  // Works with array

Compile-Time vs Runtime Extent

// Dynamic extent (size at runtime)
std::span<int> dynamic_span = vec;

// Fixed extent (size at compile time)
std::span<int, 5> fixed_span = arr;

// fixed_span.size() is constexpr
static_assert(fixed_span.size() == 5);

span Operations

std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> sp = vec;

sp.size();       // 5
sp.size_bytes(); // 5 * sizeof(int)
sp.empty();      // false
sp.data();       // Pointer to first element

sp[0] = 10;      // Modify through span
sp.front() = 20;
sp.back() = 30;

// Subspans
auto first3 = sp.first(3);   // First 3 elements
auto last2 = sp.last(2);     // Last 2 elements
auto middle = sp.subspan(1, 3);  // 3 elements starting at index 1

Read-Only Spans

void print(std::span<const int> data) {  // const elements
    for (int x : data) {
        std::cout << x << ' ';
    }
}

std::vector<int> vec = {1, 2, 3};
print(vec);  // OK: converts to span<const int>

Use Cases

Replacing Multiple Overloads

Before:

void process(const std::vector<int>& v);
void process(const std::array<int, 10>& a);
void process(const int* data, size_t size);

After:

void process(std::span<const int> data);  // Handles all cases

Safer C-Style Arrays

// Old: Easy to mismatch size
void process(const int* data, size_t size);

// New: Size is part of the span
void process(std::span<const int> data);

string_view vs const string&

Aspectstring_viewconst string&
Copy CostCheap (2 pointers)Depends (reference)
Temporary CreationNoYes (for literals)
Null-TerminationNot guaranteedGuaranteed
SubstringO(1)O(n) (copies)
Modify OriginalNoNo

Guideline: Use string_view for read-only string parameters, especially when substrings are common.

span vs vector&

Aspectspanvector&
TypeViewContainer
OwnershipNoYes
Works WithAny contiguousOnly vector
ResizeNoYes

Guideline: Use span for functions operating on contiguous data regardless of container type.

Conceptual Check

Why is std::string_view potentially dangerous?

Runtime Environment

Interactive Lab

1#include <iostream>
2#include <string_view>
3#include <span>
4#include <vector>
5 
6void print_sv(std::string_view sv) {
7 std::cout << "string_view: " << sv << " (size: " << sv.size() << ")\n";
8}
9 
10void double_values(std::span<int> data) {
11 for (int& x : data) {
12 x *= 2;
13 }
14}
15 
16int main() {
17 // string_view examples
18 print_sv("literal");
19 std::string str = "hello";
20 print_sv(str);
21
22 // span examples
23 std::vector<int> vec = {1, 2, 3, 4, 5};
24 double_values(vec);
25
26 std::cout << "After doubling: ";
27 for (int x : vec) std::cout << x << ' ';
28 std::cout << '\n';
29
30 return 0;
31}
System Console

Waiting for signal...