Using std::span
as a function parameter has several benefits over using a reference to a specific container type:
A function that takes a std::span
 can be called with any contiguous sequence of elements, regardless of how those elements are actually stored. This could be a std::vector
, a std::array
, a built-in array, or even another std::span
. This makes the function more flexible and reusable.
#include <span>
#include <vector>
#include <array>
#include <iostream>
void PrintElements(std::span<const int> elements) {
for (int i : elements) {
std::cout << i << " ";
}
std::cout << "\n";
}
int main() {
std::vector<int> vec{1, 2, 3};
std::array<int, 4> arr{4, 5, 6, 7};
int c_arr[] = {8, 9, 10};
PrintElements(vec);
PrintElements(arr);
PrintElements(c_arr);
}
1 2 3
4 5 6 7
8 9 10
When you pass a container by value, a copy of the container is made. For large containers, this can be expensive. When you pass a reference to a container, no copying is done, but the function is tied to a specific container type. With std::span
, no copying is done, and the function can work with any container type.
Using std::span
 makes it clear that the function only needs a view of the elements, and does not need to modify the container itself. This can make the code easier to understand and maintain.
You can use std::span<const T>
 to indicate that the function will not modify the elements. This is not possible with a non-const reference to a container.
void ProcessElements(
std::span<const int> elements) {
// elements cannot be modified here
}
If a function takes a reference to a container, and that container is a temporary object, the reference will be left dangling after the temporary object is destroyed. With std::span
, the caller needs to ensure that the original data outlives the span.
void ProcessElements(
const std::vector<int>& elements) {
// Dangling reference if elements is a temporary
}
void ProcessElements(
std::span<const int> elements) {
// No dangling reference, but caller must ensure
// original data outlives the span
}
However, std::span
is not always the best choice. If your function needs to modify the container itself (e.g., add or remove elements), then you need to take the container by reference. Also, std::span
doesn't work well with non-contiguous containers like std::list
or std::map
.
Answers to questions are automatically generated and may not have been reviewed.
std::span
A detailed guide to creating a "view" of an array using std::span
, and why we would want to