CppCoreGuidelines F.24 用 span 或 span_t 表示半开序列
12 June 2022
理由
不正式的/不明确的范围,容易导致错误。
例子
X* find(span<X> r, const X& v); // find v in r vector<X> vec; // ... auto p = find({vec.begin(), vec.end()}, X{}); // find X{} in vec
注意
C++ 代码中,范围的使用很普遍。一般都是隐式的,很难确保正确使用。尤其是,
(p, n)
表示一个数组 [p:p+n)
,很难理清楚是要访问 *p
后面有 n
个元素。
span<T>
和 span_p<T>
表示一个范围 [p:q)
,以 p
开始,以预测条件为真结束。
例子
void f(span<int> s) { // range traversal (guaranteed correct) for (int x : s) cout << x << ' '; cout << endl; // C-style traversal (potentially checked) for (gsl::index i = 0; i < s.size(); ++i) cout << s[i] << ' '; cout << endl; // random access (potentially checked) s[2] = 9; //s[7] = 10; // terminate called without an active exception // extract pointers (potentially checked) std::sort(&s[0], &s[s.size() / 2]); for (int x : s) cout << x << ' '; } int main() { int ss[] = {4, 3, 2, 1, 2, 3}; f(ss); return 0; }
4 3 2 1 2 3 4 3 2 1 2 3 3 4 9 1 2 3
注意
span<T>
并不保留其元素值,非常轻量,所以可以以值传递。
传递 span
对象的效率跟传递两个指针对,或指针+数量一样。
强化
- (复杂)警告:访问指针参数的时候,其范围又由另外参数指定。建议使用
span