STL:vector内部实现原理及基本用法

Posted 滔滔就是我hia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL:vector内部实现原理及基本用法相关的知识,希望对你有一定的参考价值。

1.vector类的实现

重要结构定义:

template<class T>
class myVector{
public:
    typedef T value_type;//元素类型  起别名
    typedef value_type* pointer;//
    typedef value_type* iterator;//迭代器
    typedef value_type& reference;//引用
    typedef const value_type* const_pointer;//常量指针
    typedef const value_type& const_reference;//常量引用
    typedef size_t size_type;//数据类型基本尺寸大小
private:
    iterator start;
    iterator finish;
    iterator end_of_storage;

供类内部以及派生类使用:

protected:
//分配空间并填充初始值, 不返回任何值
void __allocate_add_fill(size_type n, const T& value){
        iterator result = (iterator)malloc(n*sizeof(T));
        if (result){//result!=0  申请内存成功,在得到的内存上创建对象
            start = result;
            end_of_storage = start + n;
            finish = end_of_storage;
            while (n--){
                //指针偏移,进行赋值
                construct(result, value);//在内存上,一个个的进行构造对象
                ++result;
            }
        }
        else{
            cout << "内存不足,程序终止!" << endl;
            exit(0);
        }
    }
//分配空间 从first开始复制n个值到新空间中, 并返回新开辟的空间的首地址
    iterator __allocate_and_copy(iterator first, size_type n){
        //内存申请
        iterator result = (iterator)malloc(n*sizeof(T));
        iterator _start = result;
        if (0 != result){
            while(n--){
                construct(result, *first);
                ++result;
                ++first;
            }
            cout << endl;
        }
        else{
            cout << "内存不足,程序终止!" << endl;
            exit(0);
        }
        return _start;
    }
//将first到last迭代器之间(first,last)的元素拷贝到_start开始的内存中, 并返回 指向 拷贝完所有数据之后最后一个数据的下一个位置的指针
    iterator __copy(iterator first, iterator last, iterator _start){
        while (first < last){
            *_start++ = *first++;
        }
        return _start;
    }
//将first到last迭代器之间(first,last)的元素重新赋值
iterator __fill(iterator first, iterator last, const T& value){
    while (first < last){
        *first++ = value;
    }
    return first;
}
//自己写的 从迭代器first开始填充n个值为value的元素
iterator __fill_n(iterator first, size_type n, const T& value){
    while (n--){
        *first++ = value;
    }
    return first;
}
//自己写的  将从 [first,last)所有元素 一一依次后移, 最后的一个元素移到end的位置
void __backCopy(iterator first, iterator last, iterator end){
    while (last >= first){ //
        *end-- = *last--;
    }
}

供外部使用的接口:

public:
    //返回首元素指针
    iterator begin(){ return start; }
    const iterator begin() const { return start; }

    //返回尾元素下一个位置的指针
    iterator end(){ return finish; }
    const iterator end() const{ return finish; }

    //------------------
    //取元素  自己写
    T front(){ return *begin(); }//取vector中第一个元素
    T back(){ return *(end() - 1); }//取vector中最后一个元素

    //容器大小
    size_type size() const{ return (size_type)(end() - begin()); }

    //容器的实际大小
    size_type capacity() const{ return (end_of_storage - begin()); }

    //判断容器是否为空
    bool empty(){ return begin() == end(); }
//默认构造函数
    myVector() :start(NULL), finish(NULL), end_of_storage(NULL){ cout << "默认构造函数,不分配空间" << endl; }
//构造函数重载
    myVector(size_type n, const T& value){ __allocate_add_fill(n, value); }
    myVector(int n, const T&value){ __allocate_add_fill(n, value); }
    myVector(long n, const T&value){ __allocate_add_fill(n, value); }

    myVector(size_type n){ __allocate_add_fill(n, T()); }//??? T()??
    myVector(int n){ __allocate_add_fill(n, T()); }
    myVector(long n){ __allocate_add_fill(n, T()); }
//元素操作
    //删除最后一个元素
    void pop_back(){
        if (!empty()){
            --finish;
            destroy(finish);
        }
    }

    //删除指定位置上的元素,并返回指向删除元素的迭代器
    iterator erase(iterator position){
        if (position > begin() && position < end()){
            __copy(position + 1, finish, position);
        }
        destroy(finish);
        --finish;

        return position;
    }
//删除指定范围的元素  并返回 迭代器返回的元素
    iterator erase(iterator first, iterator last){
        if (first > begin() && first < last && last < end()){
            iterator iter = __copy(last, finish, first);
            destroy(iter, finish);
            finish -= (last - first);
            return first;
        }
    }

    //清除全部元素
    void clear(){
        erase(begin(), end());
    }

push_back函数:

//在vector容器的后面添加一个元素,值为value
    void push_back(const T& value){
        if (finish != end_of_storage){//如果新加入元素后,空间够用的话
            construct(finish, value);
            ++finish;
        }
        else{//如果新加入元素之后 空间不够用的话
            //重新分配空间
            const size_type old_size = size();
            const size_type new_size = (old_size == 0) ? 1 : 2 * old_size;//如果原空间为0,则配置1的大小,如果原空间不为0,则配置原空间二倍大小的新空间到新的地址
            iterator new_start = (iterator)malloc(new_size*sizeof(T));
            iterator new_finish = new_start;//开始时,未拷贝前,结束位置等于起始位置
            iterator new_capacity = new_start + new_size;

            //内存分配要具有原子性,即: 要么全部成功,要么全部失败
            try{//1:将原空间的全部元素拷贝到新空间 2:为新的元素设定初始值 3:调整 new_finish
                for (iterator it = begin(); it < end(); ++it){//1:将原空间的全部元素拷贝到新空间
                    construct(new_finish, *it);
                }
                construct(new_finish, value);//2:为新的元素设定初始值
                ++new_finish;//3:调整 new_finish
            }
            catch (...){//如果内存分配失败了
                destroy(new_start, new_finish);
                free(new_start);//删除申请到的内存
                new_start = NULL;
                new_finish = NULL;
                throw("重新分配内存失败!");
            }
            destroy(begin(), end());//析构,并释放原vector
            free(start);//删除原vector的内存
            start = new_start;//更改迭代器,指向新的vector
            finish = new_finish;
            end_of_storage = new_start + new_size;
        }
    }

insert函数:

//插入 在值为value的一个元素到position的位置上
    void insert(iterator position, const T& value){
        insert(position, 1, value);
    }

    //在position位置之后,插入n的值为value的元素
    void insert(iterator position, size_type n, const T& value){
        if (n == 0)return;

        if ((end_of_storage - finish) >= n){//备用空间够插入n个新元素
            T x_copy = value;
            const  size_type size_from_position_to_end = finish - position;

            iterator old_finish = finish;
            if (size_from_position_to_end > n){
                //先从pos到oldfinish拿出后n个数,放到后面
                //再将pos到剩下的几个数向后移动到oldfinish
                //插入n个value到pos->pos+n
                __copy(finish - n, finish, finish);
                finish += n;
                __backCopy(position, old_finish - n, old_finish);
                __fill(position, position + n, x_copy);
            }
            else{
                //在后面先插入多的value,然后再将pos到oldfinish的拿出来插到后面
                //然后将剩下的value放到pos到oldfinsh
                __fill_n(finish, n - size_from_position_to_end, x_copy);
                finish += n - size_from_position_to_end;
                __copy(position, old_finish, finish);
                finish += size_from_position_to_end;
                __fill(position, old_finish, x_copy);//在
            }
        }
        else{
            //重新申请空间
            const size_type old_size = size();
            size_type _max = 0;
            if (old_size > n) _max = old_size;
            else _max = n;
            const size_type len = old_size + _max;
            iterator new_start = (iterator)malloc(len * sizeof(T));
            iterator new_finish = new_start;
            //内存的分配要有原子性,即:要么全部成功,要么全部失败。
            try{
                new_finish = __copy(begin(), position, new_start);//1.将原内容 至position的所有元素(不包含position) 拷贝到新的vector
                new_finish = __fill_n(new_finish, n, value);//2.将position位置到后面的n个元素都填充为value
                new_finish = __copy(position, end(), new_finish);//3.拷贝从 position位置到end()位置的原vector的所有剩余元素
            }
            catch (...)//如果失败了
            {
                destroy(new_start, new_finish);
                free(new_start);//删除申请到的内存
                new_start = new_finish = NULL;
                throw;        //抛出异常
            }
            //析构并释放原vector
            destroy(begin(), end());
            //删除内存
            free(start);
            //调整迭代器,指向新的vector
            start = new_start;
            finish = new_finish;
            end_of_storage = new_start + len;
        }
    }
//重载操作符
    reference operator[](size_type n){ return *(begin() + n); }//取 第n个元素
    const_reference operator[](size_type n) const{ return *(begin() + n); }

    //两个容器是否相等(每个元素)
    bool operator==(const myVector&v){
        if (v.size() != size())return false;
        iterator it;
        for (it = v.begin(); it < v.end(); ++it){
            if (*it != *(begin() + (it - v.begin()))) break;
        }
        
        //比较到了最后就完全相等
        if (it == v.end()) return true;
        else return false;
    }
    
    bool operator!=(const myVector&v){
        return !(operator==(v));
    }
};

2.自定义函数

#pragma once

template<class T1, class T2>
inline void construct(T1 *p, const T2 &value){
    new (p)T1(value);      //用placement new在所指对象上创建一个对象,value是初始化对象的值
}

template<class T>
inline void destroy(T* pointer){//只做了一层包装,将指针所指的对象析构--通过直接调用类的析构函数
    pointer->~T();
}

template<class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last){//destroy的泛化版 接受两个迭代器为参数
    for (; first < last; ++first){
        destroy(&*first);//得 理解一下  &*
    }
}

inline void destroy(char*, char*){};//针对 char* 的特化版
inline void destroy(wchar_t*, wchar_t*){};//针对 wchar_t* 的特化版

3.测试代码

void display(const myVector<int> &v){
    for (myVector<int>::iterator it = v.begin(); it != v.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
}
void test(){
    cout << "test--------" << endl;
    myVector<int> v(100);
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);
    v.push_back(6);
    v.push_back(5);
    for (int i = 0; i < v.size(); ++i)
        cout << v[i] << " ";
    cout << endl;

    myVector<int>::iterator it;
    for (it = v.begin(); it != v.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
    cout << "size: " << v.size() << endl;
}
void test1(){
    cout << "test1--------" << endl;
    myVector<int> v(100);
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);
    v.push_back(6);
    v.push_back(5);

    myVector<int>::iterator it = v.begin() + 3;

    v.insert(it, 3, 300); display(v);
    v.insert(it, 4, 500); display(v);
    v.insert(it, 2, 200); display(v);
    v.insert(it, 2, 20); display(v);
    v.insert(it, 3, 30); display(v);
    v.insert(it, 4, 40); display(v);
}
void test2(){
    cout << "test2--------" << endl;
    myVector<int> v(100);
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);
    v.push_back(6);
    v.push_back(5);

    myVector<int>::iterator it = v.begin();

    v.insert(it, 300); display(v);
    v.insert(it, 500); display(v);
    v.insert(it, 200); display(v);
    v.insert(it, 20); display(v);
    v.insert(it, 30); display(v);
    v.insert(it, 40); display(v);
}

运行结果:

/*
test--------
10 9 8 7 6 5 
10 9 8 7 6 5 
size: 6
test1--------
10 9 8 300 300 300 7 6 5 
10 9 8 500 500 500 500 300 300 300 7 6 5 
10 9 8 200 200 500 500 500 500 300 300 300 7 6 5 
10 9 8 20 20 200 200 500 500 500 500 300 300 300 7 6 5 
10 9 8 30 30 30 20 20 200 200 500 500 500 500 300 300 300 7 6 5 
10 9 8 40 40 40 40 30 30 30 20 20 200 200 500 500 500 500 300 300 300 7 6 5 
test2--------
300 10 9 8 7 6 5 
500 300 10 9 8 7 6 5 
200 500 300 10 9 8 7 6 5 
20 200 500 300 10 9 8 7 6 5 
30 20 200 500 300 10 9 8 7 6 5 
40 30 20 200 500 300 10 9 8 7 6 5 
Program ended with exit code: 0
*/

引用:https://github.com/MissStrick...

以上是关于STL:vector内部实现原理及基本用法的主要内容,如果未能解决你的问题,请参考以下文章

[C++STL]vector容器用法介绍

C++STL:vector的使用及模拟实现

STL vector用法介绍

STL vector 用法

STL——vector模拟实现

C++标准模板库(STL)——vector常见用法详解