[2026] C++ std::span | Contiguous Memory View (C++20)

[2026] C++ std::span | Contiguous Memory View (C++20)

이 글의 핵심

std::span for arrays and vectors: non-owning view, subspan, bounds, const correctness, lifetime pitfalls, and C API interop.

What is span?

std::span is a lightweight view of a contiguous memory region introduced in C++20. It provides a safe, unified interface by providing a size and pointer to an array, vector, or contiguous memory. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
// 실행 예제
void process(std::span<int> data) {
    for (int x : data) {
        std::cout << x << " ";
    }
}
int arr[] = {1, 2, 3};
std::vector<int> vec = {4, 5, 6};
process(arr);  // arrangement
process(vec);  // vector

Why do you need it?:

  • Unified Interface: Treats arrays, vectors, and C arrays as one type.
  • Safety: Boundary check possible including size information
  • Performance: No copy, just reference (pointer + size)
  • Conciseness: No need to pass pointer and size separately 다음은 cpp를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Traditional method: pointer + size (inconvenient, possible error)
// 실행 예제
void process(int* data, size_t size) {
    for (size_t i = 0; i < size; ++i) {
        std::cout << data[i] << " ";
    }
}
int arr[] = {1, 2, 3};
process(arr, 3);  // Pass the size manually
// ✅ span: integrated and secure
void process(std::span<int> data) {
    for (int x : data) {  // range based for available
        std::cout << x << " ";
    }
}
process(arr);  // Size automatic inference

Characteristics of span:

  • Non-owning: Does not own the memory, only references it
  • Lightweight: Stores only pointer and size (usually 16 bytes)
  • Copyable: Copying costs are very low
  • View: Original data can be modified (const span is read-only) 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> sp{vec};
sp[0] = 10;  // Edit original vec
std::cout << vec[0];  // 10 (edited)

Structure of span: 다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// Conceptual Implementation
template<typename T>
class span {
    T* data_;
    size_t size_;
    
public:
    span(T* data, size_t size) : data_(data), size_(size) {}
    
    size_t size() const { return size_; }
    T* data() const { return data_; }
    T& operator const { return data_[index]; }
    
    // iterator
    T* begin() const { return data_; }
    T* end() const { return data_ + size_; }
};

Default use

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
#include <vector>
std::vector<int> v = {1, 2, 3, 4, 5};
// full span
std::span<int> sp1{v};
// partial span
std::span<int> sp2{v.data() + 1, 3};  // {2, 3, 4}
// size
std::cout << sp1.size() << std::endl;  // 5

Practical example

Example 1: Function parameters

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
#include <vector>
#include <array>
// unified interface
void printData(std::span<const int> data) {
    for (int x : data) {
        std::cout << x << " ";
    }
    std::cout << std::endl;
}
int main() {
    int arr[] = {1, 2, 3};
    std::vector<int> vec = {4, 5, 6};
    std::array<int, 3> stdArr = {7, 8, 9};
    
    printData(arr);     // 1 2 3
    printData(vec);     // 4 5 6
    printData(stdArr);  // 7 8 9
}

Example 2: Subrange

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// first 5
std::span<int> first5{v.data(), 5};
// last 5
std::span<int> last5{v.data() + 5, 5};
// subspan
std::span<int> sp{v};
auto middle = sp.subspan(3, 4);  // {4, 5, 6, 7}

Example 3: Bounds checking

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
void safeAccess(std::span<int> data, size_t index) {
    // boundary check
    if (index < data.size()) {
        std::cout << data[index] << std::endl;
    } else {
std::cout << "out of range" << std::endl;
    }
}
int main() {
    std::vector<int> v = {1, 2, 3};
    safeAccess(v, 1);   // 2
    safeAccess(v, 10);  // Out of range
}

Example 4: 2D array

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <span>
void processMatrix(std::span<int> data, size_t rows, size_t cols) {
    for (size_t i = 0; i < rows; ++i) {
        for (size_t j = 0; j < cols; ++j) {
            std::cout << data[i * cols + j] << " ";
        }
        std::cout << std::endl;
    }
}
int main() {
    std::vector<int> matrix = {
        1, 2, 3,
        4, 5, 6,
        7, 8, 9
    };
    
    processMatrix(matrix, 3, 3);
}

span operation

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

std::span<int> sp{v};
// size
auto size = sp.size();
auto bytes = sp.size_bytes();
// access
int first = sp.front();
int last = sp.back();
int* ptr = sp.data();
// partial range
auto sub1 = sp.first(3);      // first 3
auto sub2 = sp.last(3);       // last 3
auto sub3 = sp.subspan(2, 3); // [2] to 3

Frequently occurring problems

Problem 1: Lifespan

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Dangling
std::span<int> getDanglingSpan() {
    std::vector<int> v = {1, 2, 3};
    return std::span{v};
    // v extinction
}
// ✅ Reference disambiguation
std::span<int> getSpan(std::vector<int>& v) {
    return std::span{v};
}

Problem 2: const

아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

std::vector<int> v = {1, 2, 3};
// read only
std::span<const int> sp{v};
// ❌ No editing possible
// sp[0] = 10;  // error
// ✅ Modifiable
std::span<int> sp2{v};
sp2[0] = 10;

Issue 3: Size

아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// fixed size span
std::span<int, 3> fixedSpan{arr};
// dynamic size span
std::span<int> dynamicSpan{vec};
// ❌ Size mismatch
// std::span<int, 5> sp{arr};  // error if arr size is 3

Problem 4: Pointer conversion

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

int* ptr = getData();
size_t size = getSize();
// ✅ Wrapping with spans
std::span<int> sp{ptr, size};
// safe access
for (int x : sp) {
    std::cout << x << " ";
}

span vs pointer

아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Pointer (no size information)
void process(int* data, size_t size) {
    for (size_t i = 0; i < size; ++i) {
        std::cout << data[i] << " ";
    }
}
// ✅ span (including size)
void process(std::span<int> data) {
    for (int x : data) {
        std::cout << x << " ";
    }
}

Practice pattern

Pattern 1: Read-only view

다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

class DataProcessor {
public:
    // const span: read-only
    double calculateAverage(std::span<const double> data) const {
        if (data.empty()) return 0.0;
        
        double sum = 0.0;
        for (double value : data) {
            sum += value;
        }
        return sum / data.size();
    }
};
// use
std::vector<double> values = {1.0, 2.0, 3.0, 4.0, 5.0};
DataProcessor processor;
double avg = processor.calculateAverage(values);

Pattern 2: Sliding Window

다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

template<typename T>
void processWindows(std::span<T> data, size_t windowSize) {
    if (data.size() < windowSize) return;
    
    for (size_t i = 0; i <= data.size() - windowSize; ++i) {
        auto window = data.subspan(i, windowSize);
        
        // window processing
        std::cout << "Window [" << i << "]: ";
        for (const auto& value : window) {
            std::cout << value << " ";
        }
        std::cout << '\n';
    }
}
// use
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8};
processWindows(std::span{data}, 3);

Pattern 3: Buffer Wrapper

다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

class Buffer {
    std::vector<uint8_t> data_;
    
public:
    Buffer(size_t size) : data_(size) {}
    
    // Full buffer view
    std::span<uint8_t> asSpan() {
        return std::span{data_};
    }
    
    // read-only view
    std::span<const uint8_t> asSpan() const {
        return std::span{data_};
    }
    
    // partial view
    std::span<uint8_t> slice(size_t offset, size_t length) {
        return std::span{data_}.subspan(offset, length);
    }
};
// use
Buffer buffer(1024);
auto view = buffer.asSpan();
view[0] = 0xFF;

FAQ

Q1: What is span?

A: A lightweight view of a contiguous memory region in C++20. Pointers and sizes are provided together to provide a secure and unified interface. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> sp{vec};  // pointer + size
std::cout << sp.size() << '\n';  // 5
std::cout << sp[0] << '\n';      // 1

Q2: Does span copy data?

A: No. A span is a non-owning view, meaning it only references the original data. Copy cost is very low (only copy pointer + size). 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

std::vector<int> vec(1000000);  // big vector
// Create span: no copy (pointer + size only)
std::span<int> sp{vec};
// span copy: very fast (only copies 16 bytes)
std::span<int> sp2 = sp;

Q3: Where is span used?

A:

  • Function parameters: Integrate arrays, vectors, and C arrays
  • Partial range: slicing, windowing
  • Safe Pointer: Boundary check possible with size information included 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// unified interface
void process(std::span<int> data) {
    // Array, vector, std::array are all possible
}
int arr[] = {1, 2, 3};
std::vector<int> vec = {4, 5, 6};
std::array<int, 3> stdArr = {7, 8, 9};
process(arr);
process(vec);
process(stdArr);

Q4: Is the span size fixed?

A: Supports both dynamic size and fixed size. 아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// Dynamic size (default)
std::span<int> dynamicSpan{vec};
// Fixed size (compile time)
std::span<int, 3> fixedSpan{arr};
// Fixed size is verified at compile time
// std::span<int, 5> wrongSpan{arr};  // error: size mismatch

Q5: How do you manage the lifespan of a span?

A: span is a non-owning view, so you need to be careful about the lifetime of the original data. 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Dangling span
std::span<int> getDanglingSpan() {
    std::vector<int> vec = {1, 2, 3};
    return std::span{vec};  // vec disappears!
}
// ✅ Safe to use
std::span<int> getSpan(std::vector<int>& vec) {
    return std::span{vec};  // vec is owned by the caller
}

Q6: What is the difference between const span and span?

A:

  • const std::span: span itself is const (cannot point to other memory)
  • std::span: The data pointed to is const (data cannot be modified) 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> vec = {1, 2, 3};
// span<const int>: data read only
std::span<const int> sp1{vec};
// sp1[0] = 10;  // Error: Data cannot be modified
sp1 = std::span<const int>{};  // OK: span itself can be modified
// const span<int>: span itself is const
const std::span<int> sp2{vec};
sp2[0] = 10;  // OK: Data can be modified
// sp2 = std::span<int>{};  // Error: span itself cannot be modified

Q7: Can span be converted to a pointer?

A: It is possible. You can get a pointer with the data() method. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

std::span<int> sp{vec};
// Get pointers
int* ptr = sp.data();
// Legacy API calls
legacyFunction(ptr, sp.size());

Q8: What are span learning resources?

A:

  • “C++20 The Complete Guide” by Nicolai Josuttis
  • “Effective Modern C++” by Scott Meyers
  • cppreference.com - std::span Related posts: string_view, array, vector. One-Line Summary: std::span is a lightweight, non-owned view of a contiguous region of memory, providing a safe, unified interface.

Good article to read together (internal link)

Here’s another article related to this topic.

Practical tips

These are tips that can be applied right away in practice.

Debugging tips

  • If you run into a problem, check the compiler warnings first.
  • Reproduce the problem with a simple test case

Performance Tips

  • Don’t optimize without profiling
  • Set measurable indicators first

Code review tips

  • Check in advance for areas that are frequently pointed out in code reviews.
  • Follow your team’s coding conventions

Practical checklist

This is what you need to check when applying this concept in practice.

Before writing code

  • Is this technique the best way to solve the current problem?
  • Can team members understand and maintain this code?
  • Does it meet the performance requirements?

Writing code

  • Have you resolved all compiler warnings?
  • Have you considered edge cases?
  • Is error handling appropriate?

When reviewing code

  • Is the intent of the code clear?
  • Are there enough test cases?
  • Is it documented? Use this checklist to reduce mistakes and improve code quality.

Keywords covered in this article (related search terms)

This article will be helpful if you search for C++, span, view, array, C++20, etc.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3