美文网首页
Effective STL 第30条

Effective STL 第30条

作者: 懒生活 | 来源:发表于2022-10-07 23:22 被阅读0次

    如果是区间操作,注意确保容器具有足够的区间

    这个很矛盾, 我们害怕使用数组,就是因为数组有可能越界.为了不去考虑数组越界的问题,开始转向使用容器.因为在我们的认知中容器在新增元素的时候如果空间不够他会自动扩容. 但在区间操作函数中,如果容器的空间不够,是会有问题的.根本原因是容器能够自动扩容,只发生在push_back, insert等函数中. 如下面的代码,容器就不具有自动扩容的能力

    int transFormFun(int x)
    {
        return (x + 1000);
    }
    int main()
    {
        vector<int> intVecA;
        for (int i = 0; i < 128; i++)
        {
            intVecA.push_back(i);
        }
        vector<int> intVecB = { 1,2,3 };
        transform(intVecA.begin(), intVecA.end(), intVecB.end(), transFormFun);
    }
    

    上面这段代码在运行的时候就会崩溃.原因是transform这个区间操作会把intVecA的区间数据通过transFormFun转换后,赋值给intVecB.end()标记的容器起始位置,问题是intVecB.end()已经是容器的尾部,后续没有空间了,而transform触发的拷贝操作,不会触发容器的自动扩容操作.
    上面的代码有两个致命问题,
    问题1: 不能够那intVecB.end() 作为一个区间的开始. 很多容器的end()迭代器就是一个空值,不具备指向下一个数据空间的能力.
    问题2: 要确保intVecB的空间大于intVecA的空间,需要在transform之前通过resize确保没有问题.
    如果你的真实目的就是把intVecA的数据通过transFormFun转换后,追加放到intVecB的后面.那么正确的写法是

    int transFormFun(int x)
    {
        return (x + 1000);
    }
    
    
    int main()
    {
        vector<int> intVecA;
        for (int i = 0; i < 128; i++)
        {
            intVecA.push_back(i);
        }
        vector<int> intVecB = { 1,2,3 };
        transform(intVecA.begin(), intVecA.end(), back_inserter(intVecB), transFormFun);
    }
    

    back_inserter(intVecB) 为intVecB这个容器返回一种特殊的迭代器. 当区间函数通过这个特殊的迭代器进行赋值操作的时候, 他实际调用的是容器的push_back函数. 而push_back的调用可以安全的触发容器的自动扩容机制.

    插入用的迭代器

    back_inserter, inseter, front_inserter
    如果在上面的例子中使用front_inserter(intVecB), 为intVecB这个容器返回一种特殊的迭代器. 当区间函数通过这个特殊的迭代器进行赋值操作的时候, 他实际调用的是容器的push_front函数.(但是注意有些容器不具有push_front函数), push_front的操作是每次对容器头进行插入.
    inserter(intVecB, intVecB.begin()+intVecB.size()) 为intVecB这个容器返回一种特殊的迭代器当区间函数通过这个特殊的迭代器进行赋值操作的时候, 他实际调用的是容器的insert函数, 在指定位置进行插入.

    相关文章

      网友评论

          本文标题:Effective STL 第30条

          本文链接:https://www.haomeiwen.com/subject/wmmvartx.html