/***********************************************
* 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; }