[C++]Vector源码实现

来源:互联网 发布:云计算与智慧城市 编辑:程序博客网 时间:2024/05/17 20:28

Vector源码实现

vector是STL里最常用的容器,本文尝试着用一种相对简单的方法构建一个vector实现模板,并加上std::allocator。尽可能解释其中函数的意义。

代码实现

用一个testAllocator继承allocator。此处特化int版本。

#ifndef __TEST_H__#define __TEST_H__#include <memory>#include <iostream>class testAllocator : public std::allocator<int> {    public:        typedef std::allocator<int> Base;        //  此函数就是new功能。真正分配内存。        int * allocate(std::size_t size) {            std::cout << "Test Allocator: allocate" << std::endl;            return Base::allocate(size);        }        //  delete功能。真正释放内存。        void deallocate(int * p, std::size_t size) {            std::cout << "Test Allocator: deallocate" << std::endl;            Base::deallocate(p, size);        }        //  此函数不释放内存,只赋值。        void construct(int * p, int val) {            std::cout << "Test Allocator: Construct, value: " << val                      << std::endl;            Base::construct(p, val);        }        //  此函数不释放内存,只把值丢去。        void destroy(int * p) {            std::cout << "Test Allocator: Destroy, value: " << *p << std::endl;            Base::destroy(p);        }};#endif
#ifndef __VECTOR_H__#define __VECTOR_H__#define _a Alloc()#include "base.h"#include <memory>template< typename T, typename Alloc = std::allocator<T> >class myVector : public Base {    public:        // Constructor        myVector() {            _data = _a.allocate(1);            _size = 0;            _capacity = 1;        }        myVector(const std::size_t & size, const T & val,                 Alloc a = Alloc()) {            _data = a.allocate(size);            for (std::size_t i = 0; i < size; ++i)                a.construct(_data + i, val);            _size = _capacity = size;        }        template<typename InputIterator>            myVector(InputIterator begin, InputIterator end,                     Alloc a = Alloc()) {                _size = _capacity = end - begin;                _data = a.allocate(_size);                std::size_t cnt = 0;                for (InputIterator it = begin; it != end; ++it)                    a.construct(_data + (cnt++), *it);            }        myVector(const myVector & other) {            _size = other._size;            _capacity = other._capacity;            _data = _a.allocate(_capacity);            for (std::size_t i = 0; i < _size; ++i)                _a.construct(_data + i, other._data[i]);        }        // Destructor        ~myVector() {            for (std::size_t i = 0; i < _size; ++i)                _a.destroy(_data + i);            if (_capacity > 0)                _a.deallocate(_data, _capacity);        }        // Copy Operator        myVector & operator=(const myVector & other) {            if (&other != this) {                std::size_t i;                for (i = 0; i < _size; ++i)                    _a.destroy(_data + i);                if (_capacity > 0)                    _a.deallocate(_data, _capacity);                _size = other._size;                _capacity = other._capacity;                _data = _a.allocate(_capacity);                for (i = 0; i < _size; ++i)                    _a.construct(_data + i, other._data[i]);            }            return *this;        }        // Iterator        typedef T *         iterator;        typedef const T *   const_iterator;        inline iterator begin() {            return _data;        }        inline const_iterator begin() const {            return _data;        }        inline iterator end() {            return _data + _size;        }        inline const_iterator end() const {            return _data + _size;        }        // Capacity        inline std::size_t size() const {            return _size;        }        void resize(const std::size_t & newSize) {            std::size_t i;            if (newSize <= _size) {                for (i = newSize; i < _size; ++i)                    _a.destroy(_data + i);            } else {                if (newSize > _capacity) {                    std::size_t newCapacity = _capacity * 2;                    while (newSize > newCapacity)                        newCapacity *= 2;                    reserve(newCapacity);                }                for (i = _size; i < newSize; ++i)                    _a.construct(_data + i, T());            }            _size = newSize;        }        void resize(const std::size_t & newSize, const T & val) {            std::size_t i;            if (newSize <= _size) {                for (i = newSize; i < _size; ++i)                    _a.destroy(_data + i);            } else {                if (newSize > _capacity) {                    std::size_t newCapacity = _capacity * 2;                    while (newSize > newCapacity)                        newCapacity *= 2;                    reserve(newCapacity);                }                for (i = _size; i < newSize; ++i)                    _a.construct(_data + i, val);            }            _size = newSize;        }        inline std::size_t capacity() const {            return _capacity;        }        inline bool empty() const {            return _size == 0;        }        void reserve(const std::size_t & newCapacity) {            if (newCapacity > _capacity) {                T * temp = _a.allocate(newCapacity);                for (std::size_t i = 0; i < _size; ++i) {                    _a.construct(temp + i, _data[i]);                    _a.destroy(_data + i);                }                _a.deallocate(_data, _capacity);                _capacity = newCapacity;                _data = temp;            }        }        // Element Access        inline T & operator[](const std::size_t & index) {            return _data[index];        }        inline const T & operator[](const std::size_t & index) const {            return _data[index];        }        inline T & front() {            return _data[0];        }        inline const T & front() const {            return _data[0];        }        inline T & back() {            return _data[_size - 1];        }        inline const T & back() const {            return _data[_size - 1];        }        inline T * data() {            return _data;        }        inline const T * data() const {            return _data;        }        // Modifiers        template<typename InputIterator>            void assign(InputIterator begin, InputIterator end) {                std:size_t newSize = 0;                InputIterator it;                for (it = begin; it != end; ++it)                    ++newSize;                if (newSize > _capacity) {                    std::size_t newCapacity = _capacity * 2;                    while (newSize > newCapacity)                        newCapacity *= 2;                    reserve(newCapacity);                }                std::size_t i;                for (i = 0; i < _size; ++i)                    _a.destroy(_data + i);                for (i = 0, it = begin; i < newSize; ++i, ++it)                    _a.construct(_data + i, *it);                _size = newSize;            }        void assign(const std::size_t & newSize, const T & val) {            if (newSize > _capacity) {                std::size_t newCapacity = _capacity * 2;                while (newSize > newCapacity)                    newCapacity *= 2;                reserve(newCapacity);            }            std::size_t i;            for (i = 0; i < _size; ++i)                _a.destroy(_data + i);            for (i = 0; i < newSize; ++i)                _a.construct(_data + i, val);            _size = newSize;        }        void push_back(const T & val) {            if (_size >= _capacity)                reserve(_capacity * 2);            _a.construct(_data + (_size++), val);        }        void pop_back() {            _a.destroy(_data + (--_size));        }        void clear() {            for (std::size_t i = 0; i < _size; ++i)                _a.destroy(_data + i);            _size = 0;        }    private:        iterator _data;        std::size_t _size, _capacity;};#endif

测试文件

#ifndef __BASE_H__#define __BASE_H__// #define vector NOT_ALLOWED#define define NOT_ALLOWEDclass Base {};#endif#include <iostream>#include "test.h"#include "base.h"#include "vector.h"int main() {    typedef myVector<int, testAllocator> v;    Base * test = new v;    delete static_cast<v *>(test);    v * p1, * p2;    int t;    std::cout << "Test Constructor1:" << std::endl;    p1 = new v;    std::cout << "Size: " << p1->size() << std::endl;    delete p1;    std::cout << "Test Constructor2 and operator[]:" << std::endl;    p1 = new v(static_cast<std::size_t>(6), 6);    std::cout << "Size: " << p1->size() << std::endl;    std::cout << "Content:";    for (int i = 0; i < 2; ++i)        std::cout << ' ' << (*p1)[i];    std::cout << std::endl;    std::cin >> t;    std::cout << "Content after change:";    (*p1)[0] = t;    const v & r(*p1);    for (int i = 0; i < 2; ++i)        std::cout << ' ' << r[i];    std::cout << std::endl;    std::cout << "Test Constructor3 and iterators, including begin(), end():"              << std::endl;    p2 = new v(r.begin(), r.end());    delete p1;    std::cout << "Content:";    for (v::iterator it = p2->begin(); it != p2->end(); ++it)        std::cout << ' ' << *it;    std::cout << std::endl;    std::cout << "Test Constructor4:" << std::endl;    *(p2->begin()) = 0;    p1 = new v(*p2);    delete p2;    std::cout << "Content:";    for (std::size_t i = 0; i < p1->size(); ++i)        std::cout << ' ' << (*p1)[i];    std::cout << std::endl;    std::cout << "Test operator=:" << std::endl;    p2 = new v(static_cast<std::size_t>(8), 8);    *p2 = *p1;    *p2 = *p2;    delete p1;    std::cout << "Content:";    for (std::size_t i = 0; i < p2->size(); ++i)        std::cout << ' ' << (*p2)[i];    std::cout << std::endl;    std::cout << "Test resize1:" << std::endl;    p2->resize(2);    std::cout << "Content:";    for (std::size_t i = 0; i < p2->size(); ++i)        std::cout << ' ' << (*p2)[i];    std::cout << std::endl;    std::cout << "Test resize2:" << std::endl;    p2->resize(8, 8);    std::cout << "Content:";    for (std::size_t i = 0; i < p2->size(); ++i)        std::cout << ' ' << (*p2)[i];    std::cout << std::endl;    std::cout << "Test reserve and capacity:" << std::endl;    p2->reserve(33);    std::cout << "Capacity: " << p2->capacity() << std::endl              << "Size: " << p2->size() << std::endl;    p2->reserve(2);    std::cout << "Capacity: " << p2->capacity() << std::endl              << "Size: " << p2->size() << std::endl;    std::cout << "Test clear and empty:" << std::endl;    if (p2->empty())        std::cout << "True" << std::endl;    else        std::cout << "False" << std::endl;    p2->clear();    if (p2->empty())        std::cout << "True" << std::endl;    else        std::cout << "False" << std::endl;    std::cout << "Capcaity: " << p2->capacity() << std::endl              << "Size: " << p2->size() << std::endl;    int * arr = new int[5];    for (int i = 0; i < 5; ++i)        arr[i] = i+1;    std::cout << "Test assign:" << std::endl;    p2->assign(arr, arr+5);    std::cout << "Content:";    for (v::const_iterator it = p2->begin(); it != p2->end(); ++it)        std::cout << ' ' << *it;    std::cout << std::endl << "Size: " << p2->size()              << std::endl << "Capacity: " << p2->capacity()              << std::endl;    delete [] arr;    delete p2;    return 0;}
0 0