3
\$\begingroup\$

I have implemented an Array class using templates. I have used a std::allocator object for memory allocation. Will it be better to use operator new along with placement new for memory allocation?

array.h

#ifndef ARRAY_H
#define ARRAY_H

#include <memory>
#include <cstddef>

template <typename T> class Array;

template<typename T> void swap(Array<T> &first, Array<T> &second);

template <typename T> class Array {
    friend void swap <> (Array<T> &first, Array<T> &second);
public:
    typedef T *iterator;
    typedef const T *const_iterator;
    typedef std::size_t size_type;
    typedef T value_type;

    explicit Array(size_type size, const T& value = T());
    Array(const_iterator range_begin, const_iterator range_end);
    Array(const Array&);

    Array& operator=(const Array);

    size_type size() const;

    T& operator[](size_type i);
    const T& operator[](size_type i) const;

    iterator begin();
    const_iterator begin() const;

    iterator end();
    const_iterator end() const;

    ~Array();
private:
    iterator data; // points to the first element of the array
    iterator limit; // points to one past the last element
    iterator avail; // points to one past the allocated memory

    std::allocator<T> alloc; // for memory allocation
};

// implementation
#include <algorithm>

template<typename T> void swap(Array<T> &first, Array<T> &second)
{
    using std::swap;

    swap(first.data, second.data);
    swap(first.limit, second.limit);
    swap(first.avail, second.avail);
}

template<typename T> Array<T>::Array(size_type size, const T& value):
    data(alloc.allocate(size)), limit(data), avail(data + size)
{
    while (limit < data + size)
        alloc.construct(limit++, value);
}

template<typename T> Array<T>::Array(const_iterator range_begin,
        const_iterator range_end):
    data(alloc.allocate(range_end - range_begin)), limit(data),
    avail(data + range_end - range_begin)
{
    const_iterator it = range_begin;
    while (limit < data + range_end - range_begin) {
        alloc.construct(limit++, *it);
        ++it;
    }
}

template<typename T> Array<T>::Array(const Array &original):
    data(alloc.construct(original.size())), limit(data),
    avail(data + original.size)
{
    iterator it = original.begin();
    while (it != original.limit()) {
        alloc.construct(limit++, *it);
        ++it;
    }
}

template<typename T> Array<T>& Array<T>::operator=(const Array rhs)
{
    swap(*this, rhs);

    return *this;
}

template<typename T> typename Array<T>::size_type Array<T>::size() const
{
    return limit - data;
}

template<typename T> T& Array<T>::operator[](size_type i)
{
    return data[i];
}

template<typename T> const T& Array<T>::operator[](size_type i) const
{
    return data[i];
}

template<typename T> typename Array<T>::iterator Array<T>::begin()
{
    return data;
}

template<typename T> typename Array<T>::const_iterator Array<T>::begin() const
{
    return data;
}

template<typename T> typename Array<T>::iterator Array<T>::end()
{
    return limit;
}

template<typename T> typename Array<T>::const_iterator Array<T>::end() const
{
    return limit;
}

template<typename T> Array<T>::~Array()
{
    while (limit != data)
        alloc.destroy(--limit);

    alloc.deallocate(data, avail - data);
}
#endif
\$\endgroup\$
1
  • \$\begingroup\$ I think we'll need to know more about your intent before we can meaningfully answer questions like: "Will it be better to use operator new along with placement new for memory allocation?" \$\endgroup\$ Feb 15, 2016 at 18:24

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.