콘텐츠로 이동

C++20 std::span과 C++23 std::mdspan — 비소유 배열 뷰

std::span은 C++20에서 도입된 비소유(non-owning) 연속 메모리 뷰입니다. 배열, std::vector, std::array 등 다양한 컨테이너를 복사 없이 참조할 수 있습니다. C++23의 std::mdspan은 이를 다차원으로 확장합니다.


#include <span>
#include <vector>
#include <iostream>
void print_elements(std::span<const int> s) {
for (int v : s)
std::cout << v << ' ';
std::cout << '\n';
}
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
int arr[] = {10, 20, 30};
print_elements(v); // vector → span
print_elements(arr); // C 배열 → span
print_elements({v.data(), 3}); // 처음 3개만
}

2. 정적 익스텐트 vs 동적 익스텐트

섹션 제목: “2. 정적 익스텐트 vs 동적 익스텐트”
#include <span>
// 동적 익스텐트 (크기를 런타임에 결정)
std::span<int> dynamic_span;
// 정적 익스텐트 (크기를 컴파일 타임에 고정)
std::span<int, 4> static_span; // 항상 4개
int arr[4] = {1, 2, 3, 4};
std::span<int, 4> s = arr; // OK
// std::span<int, 3> s2 = arr; // 컴파일 오류: 크기 불일치

#include <span>
#include <array>
std::array<int, 8> data = {0,1,2,3,4,5,6,7};
std::span<int> view = data;
auto front3 = view.first(3); // {0,1,2}
auto back3 = view.last(3); // {5,6,7}
auto middle = view.subspan(2, 4); // {2,3,4,5}

4. 바이트 뷰 — as_bytes / as_writable_bytes

섹션 제목: “4. 바이트 뷰 — as_bytes / as_writable_bytes”
#include <span>
#include <cstddef>
void serialize(std::span<const std::byte> bytes) {
// 바이트 단위 직렬화
}
float f = 3.14f;
auto bytes = std::as_bytes(std::span{&f, 1});
serialize(bytes);

5. C++23 std::mdspan — 다차원 배열 뷰

섹션 제목: “5. C++23 std::mdspan — 다차원 배열 뷰”
#include <mdspan>
#include <vector>
int main() {
std::vector<double> data(6);
// 2×3 행렬로 해석
std::mdspan<double, std::extents<std::size_t, 2, 3>> mat(data.data());
mat[0, 0] = 1.0;
mat[0, 1] = 2.0;
mat[1, 2] = 6.0;
}

#include <mdspan>
#include <vector>
void matrix_multiply(
std::mdspan<const double, std::dextents<std::size_t, 2>> A,
std::mdspan<const double, std::dextents<std::size_t, 2>> B,
std::mdspan<double, std::dextents<std::size_t, 2>> C)
{
for (std::size_t i = 0; i < A.extent(0); ++i)
for (std::size_t j = 0; j < B.extent(1); ++j)
for (std::size_t k = 0; k < A.extent(1); ++k)
C[i, j] += A[i, k] * B[k, j];
}

항목T* + size_tstd::span<T>
타입 안전
범위 검사없음디버그 모드
STL 호환어려움✓ (ranges)
오버헤드없음없음 (포인터+크기)

std::span은 함수 인터페이스에서 배열 종류에 상관없이 연속 메모리를 받을 때 표준 방법입니다. T*size_t 쌍을 받는 기존 인터페이스를 std::span으로 교체하면 타입 안전성과 가독성이 동시에 향상됩니다.