为啥 fill_n() 不适用于 vector.reserve()?

Posted

技术标签:

【中文标题】为啥 fill_n() 不适用于 vector.reserve()?【英文标题】:Why fill_n() does not work with vector.reserve()?为什么 fill_n() 不适用于 vector.reserve()? 【发布时间】:2016-01-22 11:10:14 【问题描述】:

我最近在学习标准库算法,对函数fill_n(iter, n, val) 有疑问。此功能要求容器至少具有从iter 开始的n 元素。

这里是测试代码:

// Version 1, Error
vector<int> vec;
vec.reserve(10);  // Only allocate space for at least 10 elements
fill_n(vec.begin(), 10, 0);

// Version 2, OK
vector<int> vec;
vec.resize(10);  // Value initialized 10 elements
fill_n(vec.begin(), 10, 0);

// Version 3, OK
vector<int> vec;
fill_n(back_inserter(vec), 10, 0);  // Push back 10 elements via back_inserter

为什么版本 1 代码错误,而版本 2 和 3 没有?

【问题讨论】:

【参考方案1】:

reserve 只保留空间,但向量的大小保持不变。 begin 返回的迭代器不能递增到向量的末尾,并且因为它是(未更改的)大小决定了向量的末尾在哪里,所以会出现错误。

【讨论】:

【参考方案2】:

版本 1 不起作用,因为:

std::reserve 修改向量的 容量 而不是它的大小。 std::fill_n 要求容器事先具有正确的 size

第 2 版有效,因为:

std::resize确实修改了向量的大小,而不仅仅是它的容量。

版本 3 有效,因为:

std::back_inserter 将在向量上调用push_back,它添加到向量并相应地修改它的大小。

【讨论】:

【参考方案3】:

reserve 不初始化任何东西。它只是保留一些空间,因此每次推送新项目时都不会发生重新分配。 因此,例如告诉fill_n 将其结果直接推送到最后的vector 的解决方案。

改变这个:

// Version 1, Error
vector<int> vec;
vec.reserve(10);  // Only allocate space for at least 10 elements
fill_n(vec.begin(), 10, 0);

收件人:

// Version 1, Corrected
vector<int> vec;
vec.reserve(10);  // Only allocate space for at least 10 elements
fill_n(std::back_inserter(vec), 10, 0);

【讨论】:

我喜欢这个回复,但我认为应该有更明确的评论,即当使用更正的版本时,back_inserter 不会导致重新分配,因为 reserve 在之前的声明。当然,对vec 的任何进一步插入、push_back 等都可能导致重新分配。

以上是关于为啥 fill_n() 不适用于 vector.reserve()?的主要内容,如果未能解决你的问题,请参考以下文章

为啥排序不适用于矢量?

为啥 MultiBinding 不适用于 CornerRadius

为啥相等检查不适用于数组[重复]

为啥 QGridLayout 不适用于 QLabel

为啥 RegisterMessageHandler 不适用于特定主题名称?

为啥 ExcludeFromPackageFolders 不适用于 msbuild?