【问题标题】: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 没有?

【问题讨论】:

    标签: c++ c++11 vector stl-algorithm


    【解决方案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 等都可能导致重新分配。
        猜你喜欢
        • 2013-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-10
        • 2017-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多