边界与子 Span
安全地切分 Span
边界与子 Span 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
使用 subspan 进行切片
s.subspan(offset, count) 返回覆盖原始数据一部分区域的 span,不进行复制,只创建一个新的指针和长度。
#include <iostream>
#include <span>
int main() {
int buf[] = {0, 1, 2, 3, 4};
std::span<int> s(buf, 5);
auto mid = s.subspan(1, 3);
for (int x : mid) std::cout << x << " ";
std::cout << "\n"; // 1 2 3
}first 与 last
first(n) 和 last(n) 返回覆盖前面或后面 n 个元素的 span。
#include <iostream>
#include <span>
int main() {
int buf[] = {10, 20, 30, 40};
std::span<int> s(buf, 4);
auto f = s.first(2);
auto l = s.last(2);
std::cout << f[0] << " " << l[1] << "\n"; // 10 40
}子 Span 共享内存
修改子 span 会改变原始数据,因为它们指向同一个缓冲区。
#include <iostream>
#include <span>
int main() {
int buf[] = {1, 1, 1, 1};
std::span<int> s(buf, 4);
auto tail = s.last(2);
tail[0] = 99;
std::cout << buf[2] << "\n"; // 99
}size_bytes
size_bytes() 返回 span 中所有元素占用的总字节数,这对底层输入输出很有用。
#include <iostream>
#include <span>
int main() {
int buf[] = {1, 2, 3};
std::span<int> s(buf, 3);
std::cout << s.size_bytes() << "\n"; // 3 * sizeof(int)
}边界由您负责
对 span 使用 operator[] 时不会检查边界。读取 s[s.size()] 属于未定义行为。
切片前先检查
如果偏移量或数量大于 span 的大小,调用 subspan 就会产生未定义行为,请先根据 size() 进行验证。
#include <iostream>
#include <span>
int main() {
int buf[] = {1, 2, 3};
std::span<int> s(buf, 3);
size_t off = 1, cnt = 2;
if (off + cnt <= s.size()) {
auto sub = s.subspan(off, cnt);
std::cout << sub.size() << "\n";
}
}切片后可能为空
切片可能得到空 span(例如 first(0));请像处理任何空范围一样处理它。
#include <iostream>
#include <span>
int main() {
int buf[] = {1, 2};
std::span<int> s(buf, 2);
auto e = s.first(0);
std::cout << e.empty() << "\n"; // 1
}链式切片
可以继续对子 span 进行切片,因为每个子 span 都只是指向原始缓冲区的另一个视图。
#include <iostream>
#include <span>
int main() {
int buf[] = {0, 1, 2, 3, 4, 5};
std::span<int> s(buf, 6);
auto inner = s.subspan(1, 4).first(2);
std::cout << inner[0] << " " << inner[1] << "\n"; // 1 2
}分块处理
subspan 的常见用途是将大型缓冲区划分为固定大小的窗口进行遍历,以支持流式处理或批处理。
#include <iostream>
#include <span>
int main() {
int buf[] = {1, 2, 3, 4, 5, 6};
std::span<int> s(buf, 6);
for (size_t i = 0; i < s.size(); i += 2) {
auto chunk = s.subspan(i, 2);
std::cout << "[" << chunk[0] << "," << chunk[1] << "] ";
}
std::cout << "\n";
}静态范围检查
使用静态范围的 span 时,编译器可以在编译时验证某些切片大小,从而更早发现错误。
生命周期仍然适用
每个子 span 都与原始缓冲区共享生命周期。如果源对象被销毁或重新分配,所有派生出的 span 都会失效。
快速检查
检查您对子 span 和边界的理解。
回顾
您学习了边界和子 span:
subspan、first和last可以创建无需分配的切片。- 子 span 共享内存,编辑子 span 会影响原始数据。
operator[]和切片都不会检查边界,请先进行验证。- 所有子 span 都与源对象共享生命周期。
常见问题解答
「边界与子 Span」课时是免费的吗?
是的 — 「边界与子 Span」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「边界与子 Span」这节课中我会学到什么?
安全地切分 Span 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「边界与子 Span」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 定长 std::array
- std::span 基础
- 向函数传递 Span
- 边界与子 Span