template < typename T >
class vtr
public:
vtr() : elements(0), size(0), max(0) { }
void push_back(const T & v)
if size >= max, grow()
assert(size <= max)
elements[size++] = v
private:
T * elements
size_t size, max
void grow()
max = (max == 0 ? 1 : max*2)
T * const ne = new T [max]
for size_t i = 0; i < size; i++
ne[i] = elements[i]
delete [] elements
elements = ne
grow() is expensive.
void grow()
max = (max == 0 ? 1 : max*2)
T * const ne = new T [max]
for size_t i = 0; i < size; i++
ne[i] = elements[i]
delete [] elements
elements = ne
new allocates and initializes new elements.
memcpy() Optimization
for size_t i = 0; i < size; i++
ne[i] = elements[i]
with
memcpy(ne, elements, sizeof(T)*size)
new overhead.
memcpy() violates the Rule of Three in so many ways.
void grow()
max = (max == 0 ? 1 : max*2)
T * const ne =
static_cast<T *>(malloc(sizeof(T)*max))
memcpy(ne, elements, sizeof(T)*size)
free(elements)
elements = ne
push_back() is now broken.
~vtr is broken for the same reason.
memcpy() still subverts the Rule of Three.
template < typename ElementT, class Allocator = allocator<ElementT> > class vector; template < typename CharT, class Traits = char_traits<CharT>, class Allocator = allocator<CharT> > class basic_string; typename basic_string<char> string;
delete on malloc()ed storage.
free() on newed storage.
new and deletenew is responsible for allocation and
initialization.
new is complicated and confusing.
delete is responsible for clean-up and deallocation.
std::allocator<T> class is an abstraction for
storage-management policies.
<memory> header of the standard library.
template < typename T >
class allocator {
public:
T * allocator(size_t);
void deallocate(T *, size_t);
void construct(T *, const T &);
void destroy(T *);
// Lots o' other stuff.
}
allocator(i) allocates enough uninitialized storage for i
elements of type T.
sizeof(T)*i.
deallocate(p, i) frees the storage pointed to by pfor i
elements of type T.
construct(p, v) uses the T value v to initialized the
storage pointed to by p.
destroy(p) calls T's destructor on the storage pointed to by
p.
template <typename T> class avtr
public:
~avtr() { uncreate() }
private:
std::allocator<T> alloc
void grow()
max_size = max(max_size*2, ptrdiff_t(1))
T * ne = alloc.allocator(max_size)
uninitialized_copy(data, data + size, ne)
uncreate()
data = ne
void uncreate()
for i = data + size - 1; i != data; i--
alloc.destroy(i)
alloc.deallocate(data, size)
uninitialized_copy(b, e, n) copies the values in (b, e) to
the uninitialized storage pointed to by n.
T's copy constructor with *b as a parameter.
<memory>.
See the complete code.
This page last modified on 19 December 2003.