C++ std::span
std::span<T> is a small, non-owning view over a contiguous sequence of T objects. It carries both a pointer and an element count, making it a clearer function parameter than separate pointer-and-size arguments.
Simple example
The span refers to the elements owned by values, so the function modifies the original array.
Compile with C++20 or newer:
What can create a span?
A span can view contiguous storage such as a built-in array, std::array, or std::vector:
Containers such as std::list are not supported because their elements are not stored contiguously.
Read-only and writable spans
Use std::span<const T> when a function only reads elements:
A writable container can be passed to either std::span<T> or std::span<const T>. A const container can only be viewed through std::span<const T>.
Dynamic and fixed extent
The default span has a size known at runtime:
A fixed-extent span includes the required element count in its type:
Fixed extent is useful when an operation always requires an exact number of elements. Prefer dynamic extent for general-purpose sequence functions.
Access and subviews
A span supports iteration, indexing, and lightweight subviews:
Useful operations include:
| Operation | Purpose |
|---|---|
size() |
Return the number of elements. |
size_bytes() |
Return the viewed size in bytes. |
empty() |
Check whether the span has no elements. |
data() |
Return a pointer to the first element. |
front() / back() |
Access the first or last element. |
first(), last(), subspan() |
Create a smaller view without copying elements. |
Indexing is not bounds checked
Check sizes before using operator[], front(), back(), or a runtime subview count. A span knows its size, but these operations do not automatically make invalid access safe.
Possible uses
- Accept arrays,
std::array, andstd::vectorthrough one function interface. - Replace a pointer-and-count parameter such as
process(data, size). - Pass a read-only sequence with
std::span<const T>. - Modify a caller-owned buffer without copying it.
- Work on a window of a larger buffer using
subspan(). - Pass contiguous data to a C API through
data()andsize(). - Inspect an object's byte representation with
std::as_bytes().
std::as_bytes() exposes object representation; it does not define a portable serialization format.
Lifetime rules
A span does not own or extend the lifetime of its elements. The viewed storage must remain alive and must not move while the span is used.
Operations that reallocate a vector also invalidate spans into that vector:
Recreate the span after an operation that may replace or reallocate its underlying storage.
When not to use a span
- Use a container when the function must own or resize the sequence.
- Use
std::string_viewfor read-only character strings. - Use an iterator pair or a range when the data is not contiguous.
- Use a smart pointer when ownership must be shared or transferred.