向函数传递 Span
编写灵活的 API
向函数传递 Span 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
一个函数适用于多种容器
接收 std::span 的函数可以同样接受数组、向量和原始缓冲区,无需模板或重载。
#include <iostream>
#include <span>
#include <vector>
#include <array>
int sum(std::span<const int> s) {
int t = 0; for (int x : s) t += x; return t;
}
int main() {
std::vector<int> v = {1, 2, 3};
std::array<int, 2> a = {4, 5};
std::cout << sum(v) << " " << sum(a) << "\n";
}无需大小参数
旧式 C 风格接口会传递一个指针和一个单独的大小。span 将二者捆绑在一起,消除了长度不匹配导致的错误。
#include <iostream>
#include <span>
void printAll(std::span<const int> s) {
for (int x : s) std::cout << x << " ";
std::cout << "\n";
}
int main() {
int buf[] = {7, 8, 9};
printAll(buf); // size inferred
}用于只读的 const span
使用 std::span<const T> 可以声明该函数不会修改调用方的数据。
#include <iostream>
#include <span>
int maxOf(std::span<const int> s) {
int m = s[0];
for (int x : s) if (x > m) m = x;
return m;
}
int main() {
int data[] = {3, 9, 4};
std::cout << maxOf(data) << "\n"; // 9
}用于原地编辑的可变 span
非 const span 允许函数直接修改调用方的元素。
#include <iostream>
#include <span>
#include <vector>
void doubleAll(std::span<int> s) {
for (int& x : s) x *= 2;
}
int main() {
std::vector<int> v = {1, 2, 3};
doubleAll(v);
std::cout << v[2] << "\n"; // 6
}避免模板膨胀
没有 span 时,可能需要针对容器类型使用模板,从而生成许多实例。span 提供一个具体的函数签名即可直接工作。
避免复制
传递 span 从不复制元素,只有指针和长度会传入函数。
#include <iostream>
#include <span>
#include <vector>
size_t count(std::span<const int> s) { return s.size(); }
int main() {
std::vector<int> big(1000, 0);
std::cout << count(big) << "\n"; // no copy of 1000 ints
}空 Span 也没有问题
函数应妥善处理空 span;size() 为零,基于范围的循环也只会执行零次。
#include <iostream>
#include <span>
int sum(std::span<const int> s) { int t = 0; for (int x : s) t += x; return t; }
int main() {
std::span<const int> empty;
std::cout << sum(empty) << "\n"; // 0
}按值传递
Span 很小,因此请按值传递,而不是按引用传递。复制一个指针和长度几乎没有开销。
明确记录 const 意图
选择 span<const T> 还是 span<T>,调用方一眼就能看出其数据是否可能被修改。
调用方保留所有权
容器的所有权仍归调用方;span 只在调用期间借用容器。函数不得在调用结束后继续保存该 span。
现代 API 风格
接受 span 是为连续数据编写函数的惯用现代方式,灵活、安全且无需复制。
快速检查
检查您对传递 span 的理解。
回顾
您学习了如何向函数传递 span:
- 一个签名即可接受数组、向量和缓冲区。
- 使用
span<const T>实现只读;使用span<T>进行原地编辑。 - 按值传递,不会复制任何内容。
- 调用方保留所有权;调用结束后不要保存 span。
常见问题解答
「向函数传递 Span」课时是免费的吗?
是的 — 「向函数传递 Span」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「向函数传递 Span」这节课中我会学到什么?
编写灵活的 API 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「向函数传递 Span」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 定长 std::array
- std::span 基础
- 向函数传递 Span
- 边界与子 Span