为何std::span采用指针+大小而非双迭代器实现?
这个问题问到点子上了!std::span的设计完全是围绕它的核心使命来的——它是专门为连续内存区域打造的轻量级视图,不是给所有容器通用的迭代器包装器。下面具体说几个关键原因:
核心定位:只服务连续内存
std::span的初衷就是处理像C数组、std::vector、std::array这类连续存储的序列。如果换成迭代器对的设计,它就和普通的range视图没区别了,完全失去了自身的独特性。而且连续内存的最大优势就是支持O(1)随机访问,用指针+长度可以直接通过begin + n定位元素,要是用双向/单向迭代器,随机访问就得遍历,效率差远了。极致轻量与性能
span要求尽可能轻量,通常就是两个成员:T* begin和size_t count,64位系统下总共16字节,和两个迭代器的大小可能相同,但指针+长度的操作没有任何抽象开销。编译器对指针运算的优化是最直接的,不需要调用迭代器的operator[]或者operator+,性能拉满。另外,它还能直接通过data()导出底层指针,完美对接C API——很多C函数都需要指针+长度参数,span直接就能给,这是迭代器对做不到的。语义明确,避免误用
当你看到std::span<T>,立刻就能明白它指向的是连续的T类型内存,不用去猜迭代器是单向、双向还是随机访问。这种明确的语义能帮编译器提前拦截错误:比如你要是试图把std::list(非连续容器)传给span,编译器直接就报错了,从根源上避免了误用非连续内存的情况。和通用range视图分工明确
C++20已经有了完善的range库,比如std::ranges::view可以处理各种迭代器类型的序列。span不需要做“万能视图”,它只需要把连续内存的场景做到极致就行——专注才能高效,这也是标准库组件设计的一贯思路。
内容的提问来源于stack exchange,提问作者user877329

