13. 39~41
StrVec.h
#include<iostream>
#include<string>
#include<memory>
#include<initializer_list>
using namespace std;
class StrVec {
public:
StrVec() :
elements(nullptr), first_free(nullptr), cap(nullptr) {}
StrVec(const initializer_list<string>&);
StrVec(const StrVec&);
StrVec& operator=(const StrVec&);
~StrVec();
void push_back(const string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string* begin() const { return elements; }
string* end() const { return first_free; }
void reserve(size_t sz);
void resize(size_t, const string& = string()); //声明不要忘记设置缺省值
void print();
private:
static allocator<string> alloc;
void chk_n_alloc() {
if (size() == capacity()) reallocate();
}
pair<string*, string*> alloc_n_copy
(const string*, const string*);
void free();
void reallocate();
string* elements;
string* first_free;
string* cap;
};
StrVec.cpp
#include"test.h"
allocator<string> StrVec::alloc;
StrVec::StrVec(const initializer_list<string>& lst)
{
elements = alloc.allocate(lst.end() - lst.begin());
cap = first_free = uninitialized_copy(lst.begin(), lst.end(), elements);
}
StrVec::StrVec(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec& StrVec::operator=(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
free();
elements = newdata.first;
first_free = cap = newdata.second;
return *this;
}
StrVec::~StrVec()
{
free();
}
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
void StrVec::reserve(size_t sz)
{
if (sz > capacity()) {
auto newdata = alloc.allocate(sz);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + sz;
}
}
void StrVec::resize(size_t n, const string& s)
{
if (n == size())
return;
if (n < capacity()) {
if (n > size())
for (int i = 0; i < n; ++i)
alloc.construct(first_free++, s);
else
for (auto p = first_free; p != elements + n; )
alloc.destroy(--p);
first_free = elements + n;
}
else {
this->reserve(n + size());
for (int i = 0; i < n; ++i)
alloc.construct(first_free++, s);
}
}
void StrVec::print()
{
for (auto i = elements; i != first_free; ++i)
cout << *i << " ";
}
pair<string*, string*>
StrVec::alloc_n_copy(const string* b, const string* e)
{
auto data = alloc.allocate(e - b);
return { data, uninitialized_copy(b,e,data) };
}
void StrVec::free()
{
if (elements) {
//for (auto p = first_free; p != elements; )
// alloc.destroy(--p);
for_each(elements, first_free, [&](string p) {
alloc.destroy(&p);
});
alloc.deallocate(elements, cap - elements);
}
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
main.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include"test.h"
using namespace std;
void test(StrVec& s) {
cout << endl;
s.print();
cout << endl;
cout << "\tCapacity " << s.capacity() << "\tSize " << s.size() << endl;
}
int main()
{
initializer_list<string> list{ "First", "test", };
StrVec s1, s2(list), s3(s2), s4 = s3;
s1 = s2;
test(s1);
s2.push_back("Push_back Test");
test(s2);
s3.reserve(25);
test(s3);
s4.resize(8, "Resize");
test(s4);
s4.resize(3);
test(s4);
s4.resize(1, "Resize");
test(s4);
return 0;
}
13.44
String.h
#include<memory>
#include<algorithm>
using namespace std;
class String {
friend ostream& operator<<(ostream&, const String&);
public:
String() : element(nullptr), first_free(nullptr) {}
String(const char* s) {
size_t sz = strlen(s);
auto newdata = alloc.allocate(sz);
auto dest = newdata;
for (unsigned int i = 0; i != sz; ++i)
alloc.construct(dest++, s[i]);
element = newdata;
first_free = dest;
}
private:
static allocator<char> alloc;
char* element;
char* first_free;
};
main.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include"test.h"
using namespace std;
ostream& operator<<(ostream& os, const String& s) {
auto c = s.element;
while (c != s.first_free)
os << *c++;
return os;
}
int main()
{
String s1("hello");
cout << s1 << endl;
return 0;
}