Skip to content
C++ Basics: Pass Contiguous Data with std::span

C++ Basics: Pass Contiguous Data with std::span

November 2, 2026

A pointer alone does not describe a sequence length. std::span packages a pointer and an extent for contiguous data while leaving ownership with the caller.

Prepare a scratch directory

Tested on Linux x86_64 with GCC 14.2.0. Install G++ and its C++ standard-library development files, and make g++ available on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party C++ library is required.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as span-nonowning-bounds-demo.cpp:

#include <array>
#include <iostream>
#include <span>

void print_values(std::span<const int> values)
{
    std::cout << "Count: " << values.size() << "; values:";
    for (const int value : values) {
        std::cout << ' ' << value;
    }
    std::cout << '\n';
}

int main()
{
    std::array<int, 4> samples{10, 20, 30, 40};
    const std::span<const int> all_samples{samples};
    print_values(all_samples);
    const std::size_t offset = 1;
    const std::size_t count = 2;
    if (offset > all_samples.size() ||
        count > all_samples.size() - offset) {
        return 1;
    }
    const auto middle_samples = all_samples.subspan(offset, count);
    print_values(middle_samples);
    samples[1] = 25;
    print_values(middle_samples);
}

Compile and run it. The second command runs only after compilation succeeds:

g++ -std=c++20 -Wall -Wextra -Werror -pedantic span-nonowning-bounds-demo.cpp -o span-nonowning-bounds-demo &&
./span-nonowning-bounds-demo

Observed output:

Count: 4; values: 10 20 30 40
Count: 2; values: 20 30
Count: 2; values: 25 30

Read the result

The full span contains four elements. Its checked subview refers to the middle two. Updating the underlying array changes the value observed through that subview. The const element type prevents mutation through these spans; it does not make the owning array immutable.

Apply it carefully

In C++20, span indexing and subspan do not provide general runtime bounds checking. Validate dynamic offsets and counts before creating a subview. The subtraction is performed only after the offset is known to be within the span, avoiding unsigned underflow. The owner must remain alive and its storage must remain valid for every use of the span. This example uses std::array, whose storage does not reallocate.

The C++ working draft specifies the relevant library behavior. The example uses interfaces available in C++20; the current working draft also describes later additions.

Clean up

Remove only the source and executable created here, then return to the starting directory:

rm -- span-nonowning-bounds-demo.cpp span-nonowning-bounds-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect the remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on