/***********************************************
* IDE: VS2010
* FILE: Str_vec.h
***********************************************/
#ifndef STR_VEC_H
#define STR_VEC_H
#include
#include // for allocator
#include // for pair
class Str_vec
{
public:
// copy control members
Str_vec() : // the allocator member is default initialized
elements(nullptr), first_free(nullptr), cap(nullptr) { }
Str_vec(const std::string *b, const std::string *e);
Str_vec(const Str_vec &); // copy constructor
Str_vec &operator=(const Str_vec &rhs); // copy assignment
~Str_vec() { free(); } // destructor
void push_back(const std::string &); // copy the element
// add elements
size_t size() const { return first_free - elements; } //typedef unsigned int size_t
size_t capacity() const { return cap - elements; }
// iterator interface
std::string *begin() const { return elements; }
std::string *end() const { return first_free; }
std::string & operator[](std::size_t n)
{ return elements[n]; }
private:
static std::allocator alloc; // allocates the elements
std::string *elements; // pointer to the first element in the array
std::string *first_free;// pointer to the first free element in the array
std::string *cap; // pointer to one past the end of the array
// utility functions:
// used by members that add elements to the Str_vec
void chk_n_alloc()
{ if (size() == capacity()) reallocate(); }
// used by the copy constructor, assignment operator, and destructor
std::pair alloc_n_copy
(const std::string *, const std::string *);
void free(); // destroy the elements and free the space
void reallocate(); // get more space and copy the existing elements
};
#endif
/***********************************************
* IDE: VS2010
* FILE: Str_vec.cpp
***********************************************/
#include
using std::string;
#include // for uninitialized_copy
using std::allocator; using std::uninitialized_copy;
#include // for move
using std::pair;
#include "Str_vec.h"
// utility function
void Str_vec::push_back(const string &s)
{
chk_n_alloc(); // ensure that there is room for another element
// construct a copy of s in the element to which first_free points
alloc.construct(first_free++, s);
}
// the first member of the returned pair points to the
// start of the allocated memory;
// the second is pointer positioned one element past the
// last constructed element.
pair
Str_vec::alloc_n_copy(const string *b, const string *e)
{
// allocate space to hold as many elements as are in the range
string *data = alloc.allocate(e - b);
// initialize and return a pair constructed from data and
// the value returned by uninitialized_copy
return make_pair(data, uninitialized_copy(b, e, data));
}
Str_vec::Str_vec(const std::string *b, const std::string *e)
{
// copy alloc_n_copy to allocate exactly as many elements as in the range
pair newdata = alloc_n_copy(b, e);
elements = newdata.first;
first_free = cap = newdata.second;
}
// destroy the element, and then deallocate the space
// that this Str_vec itself allocated
void Str_vec::free()
{
// may not pass deallocate a 0 pointer; if element is 0,
// there's no work to do
if (elements)
{
for (string *p = first_free; p != elements; /* empyt */)
{
alloc.destroy(--p);
}
alloc.deallocate(elements, cap - elements);
}
}
// copy constructor
Str_vec::Str_vec(const Str_vec &s)
{
// call alloc_n_copy to allocate exactly as many elements as in s
pair newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
// copy-assignment operator
Str_vec &Str_vec::operator=(const Str_vec &rhs)
{
// call alloc_n_copy to allocate exactly as many elements in rhs
pair data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
void Str_vec::reallocate()
{
// we'll allocate space for twice as many elements as the current size
size_t newcapacity = size() ? 2 * size() : 1;
// allocate new memory
string *newdata = alloc.allocate(newcapacity);
// move the data from the old memory to the new
string *dest = newdata; // points to the next free position in the new array
string *elem = elements;// points to the next element in the old array
for (size_t i = 0; i != size(); ++i)
{
alloc.construct(dest++, std::move(*elem++));
}
free(); // free the old space once we've moved the elements
// update our data structure to point to the new elements
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}