能否在仅调用reserve的空std::vector上使用std::generate?
我的主函数代码
#include <vector> //#include <algorithm> #include <iostream> int main() { std::vector<char> v; int len = 2 * 5 + 1; v.reserve(len); // using for loop and push_back for (int i = 0; i < len; i++) (i % 2) ? v.push_back(' ') : v.push_back('|'); // using generate // std::generate(v.begin(), v.end(), [n = 0]() mutable { return (n++ % 2) ? ' ' : '|'; }); // std::generate_n(v.begin(), len, [n = 0]() mutable { return (n++ % 2) ? ' ' : '|'; }); for (const char& c : v) std::cout << c; return 0; }
运行情况
- 使用for循环和push_back时,输出为:
| | | | | | - 使用
std::generate无任何效果 - 使用
std::generate_n触发断言失败:Expression: cannot seek vector iterator after end
问题疑问
我理解调用reserve并不会改变begin和end迭代器之间的间距,因此无法将其传入std::generate来向v的预留内存中写入' '和'|'。请问能否将v.end扩展至len长度?或者有无其他无需使用push_back等操作、也无需先初始化预留内存再覆盖的实现方式?另外我不确定Lambda表达式是否正确,但这一点无关紧要。
解决方案
核心原因
reserve仅为vector预留内存空间(提升capacity),但不会改变vector的实际元素数量(size仍为0)。因此v.begin()和v.end()指向同一位置,std::generate遍历空范围自然无效果;std::generate_n尝试从v.begin()开始写入len个元素,但vector当前没有足够的元素位置,导致迭代器越界触发断言。
实现方法
直接设置vector的size
把v.reserve(len)替换为v.resize(len)(或直接构造时指定size:std::vector<char> v(len);),这样vector的size会被设置为len,同时会初始化元素(char类型默认初始化为空字符)。此时可以直接用std::generate或std::generate_n覆盖元素:std::vector<char> v; int len = 2 * 5 + 1; v.resize(len); // 扩展size至len,内存已预留的话不会重新分配 std::generate(v.begin(), v.end(), [n = 0]() mutable { return (n++ % 2) ? ' ' : '|'; }); // 或使用generate_n // std::generate_n(v.begin(), len, [n = 0]() mutable { return (n++ % 2) ? ' ' : '|'; });这种方式不需要手动调用
push_back,直接对已存在的元素进行覆盖。使用std::back_inserter自动扩展vector
如果不想提前设置size,可以用std::back_inserter作为迭代器传入std::generate_n,它会自动调用push_back来添加元素,无需手动操作:std::vector<char> v; int len = 2 * 5 + 1; v.reserve(len); // 可选,提前预留内存避免多次分配 std::generate_n(std::back_inserter(v), len, [n = 0]() mutable { return (n++ % 2) ? ' ' : '|'; });这种方式本质还是通过
push_back扩展vector,但无需手动写循环调用。
关于扩展v.end的问题
v.end()的位置由vector的size决定,要让它扩展至len长度,直接调用v.resize(len)即可——resize会修改vector的size,同时将end()迭代器移动到对应位置,且如果之前已经用reserve预留了足够内存,不会触发额外的内存分配。
内容的提问来源于stack exchange,提问作者o_luka02

