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

 

posted @ 2021-10-23 21:47  MicroDeLe  阅读(82)  评论(0编辑  收藏  举报