std::span in C++
The Standard Library (std) in contemporary C++ offers a variety of algorithms to carry out tasks quickly and effectively. In this article, we will examine the syntax, application, and real-world examples of std::span.
What is std::span?
Consider that we have a vector of letters or an array of numbers. Historically, pointers or iterators have been used to access these components. Although, this method can be prone to mistakes. If not handled correctly, pointers can quickly become hanging and cause crashes. As iterators don't do bounds checking, we can access elements that aren't supposed to be there.
Fortunately, the std::span method provides an easy and safe way to describe a continuous subsequence of items. It offers a glimpse into a particular segment of a longer sequence by acting as a thin wrapper over the data that is already there.
Some key characteristics of std::span:
Several key characteristics of the std::span in C++ are as follows:
- Non-Owning Reference: Std::span does not own the underlying data it refers to. It only offers a method for accessing and working with a particular portion of an array, vector, or other contiguous container that already exists.
- Lightweight: Std::span is an efficient design with a small memory footprint. In order to minimize resource utilization, it usually comprises two pointers (starting and ending) and a size value.
- Contiguous Focus: Contiguous data structures are the exclusive domain of std::span. It is inappropriate for non-contiguous structures like linked lists.
- Safety precautions: Bounds checking techniques are built into std::span. Std::span ensures that we stay inside the allowed range when we access elements, avoiding out-of-bounds problems.
Creating std::span Objects
There are several ways to create std::span objects:
1. From an Array:
Let us take an example to create std::span objects using an array in C++.
#include <iostream>
#include <span>
int main() {
int numbers[] = {1, 2, 3, 4, 5};
std::span<int> subarray = numbers; // Spans the entire array
// Accessing and printing elements in the subarray
std::cout << "Subarray elements: ";
for (int elem : subarray) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-span-in-cpp1.png)
2. From a Subrange:
Let us take an example to create std::span objects using a subrange in C++.
#include <iostream>
#include <vector>
#include <span>
int main() {
std::vector<char> message = {'H', 'e', 'l', 'l', 'o'};
std::span<char> first_three(message.begin(), message.begin() + 3);
std::cout << "First three characters: ";
for (char c : first_three) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-span-in-cpp2.png)
3. With Static Extent:
Let us take an example to create std::span objects using static extent in C++.
#include <iostream>
#include <span>
int main() {
int fixed_data[10];
std::span<int, 10> fixed_span(fixed_data); // Specifies size at compile time
// Assigning values to the elements of the fixed_data array
for (int i = 0; i < 10; ++i) {
fixed_data[i] = i * 2;
}
// Accessing and printing elements in the fixed_span
std::cout << "Elements in the fixed_span: ";
for (int elem : fixed_span) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-span-in-cpp3.png)
4. From a Range (C++23):
Let us take an example to create std::span objects using a range in C++.
#include <iostream>
#include <span>
int main() {
int data[] = {7, 8, 9};
std::span<int> range_span = {std::data(data), std::size(data)}; // Uses std::data and std::size
// Accessing and printing elements in the range_span
std::cout << "Elements in the range_span: ";
for (int elem : range_span) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading -->
<h2 class=](https://static.tutorialandexample.com/cpp/std-span-in-cpp4.png)
Once we have a std::span object, we can use it to access and manipulate the underlying elements:
1. Iterating:
Let us take an example to illustrate how we can access and manipulate the std::span objects using iterating in C++.
#include <iostream>
#include <span>
int main() {
int numbers[] = {1, 2, 3, 4, 5};
std::span<int> subarray = numbers;
// Iterating over the elements of the subarray
std::cout << "Iterating: C++" << std::endl;
for (int element : subarray) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-span-in-cpp5.png)
2. Element Access:
Let us take an example to illustrate how we can access and manipulate the std::span objects using element access in C++.
#include <iostream>
#include <span>
int main() {
int numbers[] = {1, 2, 3, 4, 5};
std::span<int> subarray = numbers;
int first_element = subarray[0]; // Accesses the first element
std::cout << "First element: " << first_element << std::endl;
subarray[2] = 10; // Modifies the third element
std::cout << "Modified subarray: ";
for (int element : subarray) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-span-in-cpp6.png)
3. Subspan Creation:
Let us take an example to illustrate how we can access and manipulate the std::span objects using subspan creation in C++.
#include <iostream>
#include <vector>
#include <span>
int main() {
std::vector<char> message = {'H', 'e', 'l', 'l', 'o'};
std::span<char> first_three(message.begin(), message.begin() + 3); // Spans the first three characters
std::span<char> last_two = first_three.subspan(1); // Creates a subspan of the last two characters
// Printing the elements in the last_two subspan
std::cout << "Last two characters: ";
for (char c : last_two) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
Output:
![std::span in C++/>
<!-- /wp:html -->
<!-- wp:heading -->
<h2 class=](https://static.tutorialandexample.com/cpp/std-span-in-cpp7.png)
Several benefits of std::span in C++ are as follows:
- Enhanced Security: Out-of-bounds access is prevented via bounds checking in std::span, which results in more dependable and sturdy code.
- Enhanced Readability: By clearly describing the data it refers to, std::span improves code readability and makes the purpose clear.
- Generic Programming: The std::span promotes generic functions and algorithms by interacting with a variety of contiguous containers.
- Decreased Verbosity: In syntax, std::span is more concise than raw pointers and iterators with explicit size checks.