• vector


    array 是C++自带的

    array是静态空间,一旦配置了就不能改变;如果要换个大的空间,就要由客户自己来完成:重新申请新空间,然后将元素都从旧地址搬移到新地址,再将原空间释放。

    vector是动态空间,随着元素加入,其内部机制会自动扩充空间以容纳新元素。

    看看vector的构造函数及析构函数

     // 默认构造出的vector不分配内存空间  
        vector() : start(0), finish(0), end_of_storage(0) {}  
        vector(size_type n, const T& value) { fill_initialize(n, value); }  
        vector(int n, const T& value) { fill_initialize(n, value); }  
        vector(long n, const T& value) { fill_initialize(n, value); }  
        // 需要对象提供默认构造函数  
        explicit vector(size_type n) { fill_initialize(n, T()); }  
        vector(const vector<T, Alloc>& x)  
        {  
            start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());  
            finish = start + (x.end() - x.begin());  
            end_of_storage = finish;  
        }  
    
    void fill_initialize(size_type n, const T& value)  
        {  
            start = allocate_and_fill(n, value);  
            finish = start + n;                         // 设置当前使用内存空间的结束点  
            // 构造阶段, 此时不多分配内存,分配的空间就是size_type n个  
            // 所以要设置内存空间结束点和 已经使用的内存空间结束点相同  
            end_of_storage = finish;  
        }  
    
    iterator allocate_and_fill(size_type n, const T& x)  
        {  
            iterator result = data_allocator::allocate(n);  
            uninitialized_fill_n(result, n, x);  
            return result;  
        }  
    
    
    ~vector()  
        {  
            destroy(start, finish);    //析构对象  
            deallocate();              //释放内存  
        }  
    
    
    void deallocate()  
        {  
            // 由于使用的是data_allocator进行内存空间的分配,  
            // 所以需要同样使用data_allocator::deallocate()进行释放  
            // 如果直接释放, 对于data_allocator内部使用内存池的版本  
            // 就会发生错误  
            if (start)  
                data_allocator::deallocate(start, end_of_storage - start);  
        }  

    insert()或者push_back()当元素的内存不足时都有内部函数insert_aux()实现,它能实现vector内存不足时,扩大内存至2倍并且把原来的元素移至新地方,同时销毁原来的内存

    template <class T, class Alloc>  
        void insert_aux(iterator position, const T& x)  
        {  
            if (finish != end_of_storage)    // 还有备用空间  
            {  
                // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值  
                construct(finish, *(finish - 1));  
                ++finish;  
                T x_copy = x;  
                copy_backward(position, finish - 2, finish - 1);  
                *position = x_copy;  
            }  
            else   // 已无备用空间  
            {  
                const size_type old_size = size();  
                const size_type len = old_size != 0 ? 2 * old_size : 1;  
                // 以上配置元素:如果大小为0,则配置1(个元素大小)  
                // 如果原大小不为0,则配置原来大小的两倍  
                // 前半段用来放置原数据,后半段准备用来放置新数据  
      
                iterator new_start = data_allocator::allocate(len);  // 实际配置  
                iterator new_finish = new_start;  
                // 将内存重新配置  
                try  
                {  
                    // 将原vector的安插点以前的内容拷贝到新vector  
                    new_finish = uninitialized_copy(start, position, new_start);  
                    construct(new_finish, x);  //为新元素设定初值x  
                    ++new_finish;              //调整水位  
                    // 将安插点以后的原内容也拷贝过来  
                    new_finish = uninitialized_copy(position, finish, new_finish);  
                }  
                catch(...)  
                {  
                    // 回滚操作  
                    destroy(new_start, new_finish);  
                    data_allocator::deallocate(new_start, len);  
                    throw;  
                }  
                // 析构并释放原vector  
                destroy(begin(), end());  
                deallocate();  
      
                // 调整迭代器,指向新vector  
                start = new_start;  
                finish = new_finish;  
                end_of_storage = new_start + len;  
            }  
        }  

    注意重新分配内存时原来的迭代器都会失效!!!

    template <class T, class Alloc>  
        void insert(iterator position, size_type n, const T& x)  
        {  
            if (n != 0)     //当n不等于0才进行所有操作  
            {  
                if (size_type(end_of_storage - finish) >= n)  
                {      // 剩下的备用空间大于等于“新增元素的个数”  
                    T x_copy = x;  
                    // 以下计算插入点之后的现有元素个数  
                    const size_type elems_after = finish - position;  
                    iterator old_finish = finish;  
                    if (elems_after > n)  
                    {  
                        // 插入点之后的现有元素个数 大于 新增元素个数  
                        //也就是在原来容器的空间够用  
                        uninitialized_copy(finish - n, finish, finish);  
                        finish += n;    // 将vector 尾端标记后移  
                        copy_backward(position, old_finish - n, old_finish);  
                        fill(position, position + n, x_copy); // 从插入点开始填入新值  
                    }  
                    else  
                    {  
                        // 插入点之后的现有元素个数 小于等于 新增元素个数  
                        uninitialized_fill_n(finish, n - elems_after, x_copy);  
                        finish += n - elems_after;  
                        uninitialized_copy(position, old_finish, finish);  
                        finish += elems_after;  
                        fill(position, old_finish, x_copy);  
                    }  
                }  
                else  
                {   // 剩下的备用空间小于“新增元素个数”(那就必须配置额外的内存)  
                    // 首先决定新长度:就长度的两倍 , 或旧长度+新增元素个数  
                    const size_type old_size = size();  
                    const size_type len = old_size + max(old_size, n);  
                    // 以下配置新的vector空间  
                    iterator new_start = data_allocator::allocate(len);  
                    iterator new_finish = new_start;  
                    __STL_TRY  
                    {  
                        // 以下首先将旧的vector的插入点之前的元素复制到新空间  
                        new_finish = uninitialized_copy(start, position, new_start);  
                        // 以下再将新增元素(初值皆为n)填入新空间  
                        new_finish = uninitialized_fill_n(new_finish, n, x);  
                        // 以下再将旧vector的插入点之后的元素复制到新空间  
                        new_finish = uninitialized_copy(position, finish, new_finish);  
                    }  
    #         ifdef  __STL_USE_EXCEPTIONS  
                    catch(...)  
                    {  
                        destroy(new_start, new_finish);  
                        data_allocator::deallocate(new_start, len);  
                        throw;  
                    }  
    #         endif /* __STL_USE_EXCEPTIONS */  
                    destroy(start, finish);  
                    deallocate();  
                    start = new_start;  
                    finish = new_finish;  
                    end_of_storage = new_start + len;  
                }  
            }  
        }  
    };  

    最后总结一下:vector的用法:

    begin(),end(),size(),capacity(),empty(),operator[]

    front(), back(), push_back(), pop_back(), erase(position)

    vector(2,9) //存2个9

  • 相关阅读:
    QT UAC问题汇总贴
    被动的流氓
    Web前端优化需要注意的点
    VS快捷键
    延时过程中要加上app.processEvents(),进度条里也要加上这句
    Nim语言:Pascal的语法,Python的缩进
    QString转换成LPCWSTR
    Pascal编译器大全(非常难得)
    WCF学习心得----(三)服务承载
    SafeSEH原理及绕过技术浅析
  • 原文地址:https://www.cnblogs.com/daocaorenblog/p/5299891.html
Copyright © 2020-2023  润新知