C++fill_n填充前N个元素

2026-04-11 15:10:32 954阅读 0评论

C++里fill_n不是“填满”,是“填前N个”

刚学STL时,我第一次看到fill_n,下意识以为它和fill差不多,只是多了个数量限制——结果写错两次才明白:fill_n不检查容器实际大小,只管从起点开始写N个,越界就崩给你看

这不是玄学,是C++对程序员的诚实提醒:它不替你做边界判断,只负责把事情干得精准、干脆。


fill_n的函数签名长这样:

template<class ForwardIterator, class Size, class T>
void fill_n(ForwardIterator first, Size n, const T& value);

关键在参数顺序和语义:first是起点,n是“要填多少个”,value是填什么。它不关心first后面有没有N个位置——它只相信你传进来的迭代器合法,且从那里起至少有N个可写单元。

换句话说:
✅ 它可以填vector的前3个元素;
✅ 也能填array的后5个位置(只要你传的是对应迭代器);
❌ 但如果你对一个只有2个元素的vector调用fill_n(v.begin(), 5, 42),程序大概率在运行时崩溃——标准没义务拦你,它只保证“按你说的做”。


实际用的时候,最容易踩的坑不是语法,而是误把fill_n当“安全填充”用。比如有人想清空某段数据,顺手写:

vector<int> v = {1, 2, 3};
fill_n(v.begin(), 10, 0); // 错!v只有3个元素

这代码编译通过,运行却可能触发堆栈破坏或访问违规。真正该做的,是先确认容量或大小是否足够

if (v.size() >= 10) {
    fill_n(v.begin(), 10, 0);
} else {
    // 或者扩容:v.resize(10, 0);
}

别嫌麻烦——C++里很多“便利函数”都自带责任契约:你提供合法前提,它交付确定行为。


fill_n真正的高光时刻,往往出现在非连续内存或自定义缓冲区场景。比如处理一块原始内存:

int* buf = new int[100];
fill_n(buf, 50, -1); // 填前50个为-1,干净利落
// ……后续逻辑用到buf[0]~buf[49],其余暂不关心

这里fill_n比循环赋值更清晰,比memset更类型安全(不会把double当字节清零)。它不依赖容器封装,直接作用于迭代器——只要能++、能解引用,它就认

再比如配合back_inserter?不行。fill_n要求前向迭代器(可多次遍历),而back_inserter返回的是输出迭代器(只能写一次)。这点常被忽略,但恰恰说明:fill_n的设计哲学是“覆盖已有位置”,而非“扩展容器”


另一个容易被低估的细节:fill_n支持任意可复制类型的value,包括自定义类:

struct Point { int x, y; };
vector<Point> pts(5);
fill_n(pts.begin(), 3, {10, 20}); // ✅ 调用Point的拷贝构造

只要value能隐式转换为目标类型(或存在匹配构造),它就能填。这比手写循环直观得多,也比assign更轻量——assign会先清空再插入,fill_n只改已有元素。


最后说个实用技巧:fill_ncopy_n经常搭档出场。比如把一段数据复制并覆盖目标区域的前N位:

vector<int> src = {100, 200, 300, 400};
vector<int> dst = {1, 2, 3, 4, 5, 6};
copy_n(src.begin(), 3, dst.begin()); // dst前3个变成100/200/300
// 等价于 fill_n(dst.begin(), 3, ???) 吗?不等价——copy_n搬数据,fill_n设固定值。

分清这个区别,才能选对工具。想批量设相同值?用fill_n。想搬运一段内容?用copy_ncopy。它们不是替代关系,是分工关系。


回到开头那个问题:fill_n为什么叫“n”而不是“size”或“count”?因为标准库一贯克制——它不承诺安全,不隐藏成本,不假装智能。它就站在那里,等你给出确切起点和确切数量,然后一丝不苟地执行。

写C++久了会发现,这类函数像老焊工:不废话,不兜底,但你给准了尺寸,它焊出来的缝,严丝合缝。

下次调用fill_n前,花半秒问问自己:起点可靠吗?N个位置真实存在吗?值的类型匹配吗?
三个问题答完,fill_n就不再是潜在风险点,而成了你手里一把趁手的刻刀——削铁如泥,也只削你指定的那一段。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,954人围观)

还没有评论,来说两句吧...

目录[+]