c++oding="utf-8" ?>
最常用安全方式是用迭代器构造新vector;c++20起可用std::span实现零拷贝视图,但需确保原vector生命周期长于span。

用 std::vector::assign 或构造函数截取连续子段
直接“截取”不是 vector 的原生操作,但可以用迭代器构造新 vector,这是最常用、最安全的方式。关键不是找“截取函数”,而是用 begin() + 偏移和 end() + 偏移生成合法迭代器范围。
- 确保起始位置
start和长度len合法:start >= 0 && start = 0 && start + len - 推荐写法:
std::vector<int> sub(v.begin() + start, v.begin() + start + len);</int> - 不要写
v.begin() + start + len超出范围——这会触发未定义行为,Debug 模式下可能断言失败,Release 下静默崩溃 - 如果只是临时读取、不需拷贝,优先考虑
std::span(C++20)或裸指针+长度,避免冗余内存分配
用 std::vector::erase 实现“原地截取”(保留前 N 个)
如果你本意是“只留下开头一部分”,erase 比构造新 vector 更省内存,尤其对大 vector。
- 保留前
n个元素:v.erase(v.begin() + n, v.end()); - 保留中间一段(比如从索引 2 开始、长 5):先删前面,再删后面——但注意两次 erase 可能触发多次内存移动,不如一次性构造新 vector 干净
-
erase后v.capacity()不变,如果后续不再追加,可调用v.shrink_to_fit()释放多余容量(但不保证成功)
常见错误:越界、空 vector、迭代器失效
这些不是语法错误,编译能过,但运行时崩得莫名其妙。
- 对空 vector 写
v.begin() + 1→ 迭代器越界,UB;务必先检查v.size() >= start + len - 误用
at()截取:它只返回单个元素,v.at(i)不是切片接口 - 把
end()当作最后一个元素位置:它是尾后迭代器,v.end() - 1才是末元素,v.end() - len才是倒数第 len 个起点 - 在循环中边遍历边
erase边截取?迭代器立刻失效,必须用返回值(如erase返回新有效迭代器)或改用反向遍历
C++20 起可用 std::span 零拷贝视图
如果你不需要拥有数据,只是想“看一段”,std::span 是更轻量、更现代的选择,没有拷贝开销,也不影响原 vector 生命周期。
- 示例:
std::span<const int> view(v.data() + start, len);</const> - 注意:
v必须持续有效,view不管理内存;若v被移动或析构,view立即悬空 - 不支持所有编译器默认开启 C++20,需确认编译选项(如
-std=c++20)和标准库版本(libstdc++ 11+ / MSVC 19.30+)
实际项目里,90% 的“截取”需求本质是“构造一个副本子集”,直接用迭代器构造最直白;真要零拷贝,就认真管好生命周期——这点容易被忽略,一出问题很难定位。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











