[C++]Vector源码实现

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_ALLOWED

class 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;
}

你可能感兴趣的:([C++]Vector源码实现)