C++ primer 第五版13.39代码
class StrVec{ public: StrVec(); // 构造函数 StrVec(const StrVec&); // 拷贝构造 StrVec &operator=(const StrVec&); // 拷贝赋值构造 ~StrVec(); // 析构函数 void pushBack(const string &); // 添加元素 size_t size(){return initEndPtr-beginPtr;}; // 获取构造的元素个数 size_t capacity(){return endPtr-beginPtr;}; // 获取开辟内存空间大小 [[nodiscard]] string *begin() const{return beginPtr;}; // 获取构造元素的首指针 [[nodiscard]] string *end() const{return initEndPtr;}; // 获取构造元素的尾指针 private: static pair<string*, string*> allocCopy(string*, string*); // 拷贝操作 void free(); // 释放空间 void reAlloc(); // 重新开辟内存 static allocator<string> alloc; // 用于分配对象 string *beginPtr; // 开辟内存首指针 string *initEndPtr; // 构造元素首指针 string *endPtr; // 开辟内存尾指针 }; allocator<string> StrVec::alloc; // 静态变量需要类外初始化 StrVec::StrVec(): beginPtr(nullptr), initEndPtr(nullptr), endPtr(nullptr) {} pair<string *, string *> StrVec::allocCopy(string *b, string *e) { auto data = alloc.allocate(e - b); // 开辟内存 return {data, uninitialized_copy(b, e, data)}; // 拷贝元素 } StrVec::StrVec(const StrVec &rhs) { auto ptr = allocCopy(rhs.begin(), rhs.end()); beginPtr = ptr.first; endPtr = initEndPtr = ptr.second; } StrVec &StrVec::operator=(const StrVec &rhs) { if (this == &rhs) return *this; auto ptr = allocCopy(rhs.begin(), rhs.end()); // 先开辟空间后释放 free(); beginPtr = ptr.first; endPtr = initEndPtr = ptr.second; return *this; } void StrVec::free() { if (beginPtr){ for (auto ptr = initEndPtr; ptr != beginPtr ;) alloc.destroy(--ptr); // 析构元素 alloc.deallocate(beginPtr, capacity()); // 释放内存 } } StrVec::~StrVec() { free(); } void StrVec::pushBack(const string &str) { if (size() == capacity()) reAlloc(); // 内存不足是重写分配内存 alloc.construct(initEndPtr++, str); } void StrVec::reAlloc() { auto newCapacity = size()? 2*size(): 1; auto newData = alloc.allocate(newCapacity); // 分配新内存 auto dest = newData; auto res = beginPtr; for (auto i = 0; i < size(); ++i) alloc.construct(dest++, move(*res++)); // 构造 free(); // 释放原内存 beginPtr = newData; // 更新指针 initEndPtr = dest; endPtr = newData + newCapacity; }