为啥 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