C++primer5th模拟vector之StrVec类

本文介绍了一个自定义字符串向量类StrVec的设计与实现,重点讲解了内存分配、复制与移动操作,并解决了static alloc引发的编译问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

出现的问题:书中alloc为static,编译时连接错误,不使用static可正常运行。因为在c++11中,static必须要初始化
//现有知识储备不知道怎么给alloc初始化,所以……暂时去掉static

StrVec.h头文件内容为

#pragma once
#ifndef STRVEC_H
#define STRVEC_H
#include<string>
#include<memory>
#include<utility>//move
#include<initializer_list>
using std::string;
using std::pair;
using std::allocator;
using std::initializer_list;
//成员elements, first_free,cap----工具函数:alloc_n_copy, free, chk_n_alloc, reallocate

class StrVec {
public:
    StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr) {}//默认构造函数
    StrVec(initializer_list<string> v1);
    StrVec(const StrVec&);//拷贝构造函数
    StrVec::StrVec(StrVec &&s) noexcept:elements(s.elements), first_free(s.first_free), cap(s.cap) 
    { s.elements = s.cap = s.first_free = nullptr; }//移动构造函数
    StrVec& operator = (const StrVec&);//拷贝赋值运算符
    StrVec& operator = (StrVec &&s);//移动赋值运算符
    ~StrVec() { free(); }//析构

    void push_back(const string&);
    size_t size() { return first_free - elements; }
    size_t capacity() { return cap - elements; }
    string* begin() const { return elements; }
    string* end() const { return first_free; }
    size_t capacity() const { return cap - elements; }
    void reserve(size_t);
    void resize(size_t n);
    void resize(size_t n, const string &s);
private:
    allocator<string> alloc;//alloc用来分配内存
    pair<string*, string*> alloc_n_copy(const string*, const string*);
    void chk_n_alloc() { if (size() == capacity()) reallocate(); }
    void free();
    void reallocate();
    void reallocate(size_t);
    string *elements;
    string *first_free;
    string *cap;
};
void StrVec::push_back(const string& s)
{
    chk_n_alloc();
    alloc.construct(first_free++, s);
}
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()
{
//用lambda表达式的版本
//  for_each(elements, first_free, [](string &s) {alloc.destroy(&s); });//此语句要求alloc为static类型
    if (elements) {
        for (auto p = first_free; p != elements;)
            alloc.destroy(--p);
        alloc.deallocate(elements, cap - 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 data = alloc_n_copy(s.begin(), s.end());
    free();//干掉左侧的
    elements = data.first;
    first_free = cap = data.second;
    return *this;
}
StrVec& StrVec::operator = (StrVec &&s)
{
    if (this != &s) {
        free();
        elements = s.elements;
        first_free = s.first_free;
        cap = s.cap;
        s.elements = s.first_free = s.cap = nullptr;
    }
    return *this;
}
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++));//调用move表示希望用 string的移动构造函数
    free();//移动完元素后释放旧内存
    //
    elements = newdata;
    first_free = dest;
    cap = elements + newcapacity;
}
//
void StrVec::reallocate()
{
    auto newcapacity = size() ? 2 * size() : 1;
    auto first = alloc.allocate(newcapacity);
    //移动构造,uninitialized_copy 调用 construct将元素 移动构造
    auto last = uninitialized_copy(make_move_iterator(begin()), make_move_iterator(end()), first);
    free();
    elements = first;
    first_free = last;
    cap = elements + newcapacity;
}
void StrVec::reallocate(size_t newcapacity)
{
    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;
}
StrVec::StrVec(initializer_list<string> v1)
{
    auto newdata = alloc_n_copy(v1.begin(), v1.end());
    elements = newdata.first;
    first_free = cap = newdata.second;
}
void StrVec::reserve(size_t t)
{
    if (t > capacity())
        reallocate(t);
}
void StrVec::resize(size_t n)
{
    if (n > size())
        while (size() < n)
            push_back("");
    else if (n < size()) {
        while (size() > n)
            alloc.destroy(--first_free);
    }
}
void StrVec::resize(size_t n, const string &s)
{
    if (n > size()) {
        while (size() < n)
            push_back(s);
    }
}
#endif // !STRVEC_H

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值