深入理解C++ Vector类的实现,简单详细(附源码)

深入理解C++ Vector类的实现及测试

引言

在C++中,标准模板库(STL)的std::vector是一个强大的动态数组容器。然而,为了更好地理解其内部机制和学习模板类的实现方式,我们可以亲自动手实现一个简化版的 Vector 类。在本文中,我们将介绍自定义的 Vector 类,并通过测试用例展示其功能。
本篇面向的是初学者,旨在帮助他们了解vector的实现。
提供详细的过程的同时附源码,也是为了让自己的进步,共勉之。

Vector 类主要成员和构造函数

template <typename T>
class Vector {
public:
    typedef T value_type;
    typedef T* iterator;

    Vector() : _start(nullptr), _finish(nullptr), _end(nullptr) {}

    // ...
private:
    iterator _start;
    iterator _finish;
    iterator _end;
};
  1. Vector 是一个模板类,使用 T 表示元素的类型。
  2. value_type 定义了元素的类型,iterator 定义了迭代器类型。
  3. _start_finish_end 是迭代器,用于跟踪容器的起始、元素结束和容器末尾位置。

push_back 函数

void push_back(const value_type &x) {
    if (capacity() == 0 || capacity() == size()) {
        reserve((capacity() == 0) ? 1 : capacity() * 2);
    }
    *_finish = x;
    ++_finish;
}
  1. push_back 将元素添加到容器的末尾。
  2. 如果容器的容量为零或者容量已满,调用 reserve 函数进行扩容。
  3. 将元素添加到 _finish 指向的位置,然后将 _finish 向后移动。

pop_back 函数

void pop_back() {
    if (!empty()) {
        --_finish;
        std::cout << "弹出元素: " << *_finish << std::endl;
    } else {
        std::cout << "容器为空,无法弹出元素." << std::endl;
    }
}
  1. pop_back 从容器末尾弹出一个元素。
  2. 如果容器不为空,将 _finish 向前移动一个位置,并打印弹出的元素。
  3. 如果容器为空,输出一条相应的提示信息。

reserve 函数

void reserve(size_t newCapacity) {
    value_type* tmp = new value_type[newCapacity]();
    size_t size1 = size();
    if (_start) {
        for (size_t i = 0; i < size1; i++) {
            tmp[i] = _start[i];
        }
    }
    delete[] _start;
    _start = tmp;
    _finish = _start + size1;
    _end = _start + newCapacity;
}
  1. reserve 函数用于预留足够的容量,以便存储指定数量的元素。
  2. 创建一个新的数组 tmp,将原有元素复制到新数组。
  3. 释放原有内存,将 _start 指向新数组,更新 _finish_end

insert 函数

void insert(const value_type &x, const size_t &pos) {
   if (pos > size()) {
            cout << "越界: 无法在指定位置插入元素." << endl;
            return;
        }
        if (capacity() == 0) {
            reserve(1);
            *_finish = x;
            ++_finish;
        } else if (size() == capacity()) {
            size_t size1 = size();
            size_t cap = capacity();
            value_type* tmp = new value_type[2 * capacity()]();
            for (size_t i = 0; i < pos; i++) {
                tmp[i] = _start[i];
            }
            tmp[pos] = x;
            for (size_t i = pos; i < size1; i++) {
                tmp[i + 1] = _start[i];
            }
            delete[] _start;
            _start = tmp;
            _finish = _start + size1 + 1;
            _end = _start + 2 * cap;
        } else {
            for (int i = size(); i > pos; i--) {
                _start[i] = _start[i - 1];
            }
            _start[pos] = x;
            _finish = _start + size() + 1;
        }
}
  1. insert 函数用于在指定位置插入元素。
  2. 如果插入位置超出当前元素个数,输出提示信息并返回。

erase 函数

void erase(const size_t &pos) {
    if (pos >= 0 && pos < size()) {
        iterator begin = _start + pos;
        while (begin != _finish) {
            *begin = *(begin + 1);
            ++begin;
        }
        --_finish;
        //--_end;
    } else {
        std::cout << "越界: 无法删除指定位置的元素." << std::endl;
    }
}
  1. erase 函数用于删除指定位置的元素。
  2. 如果位置合法,从指定位置开始,将后续元素向前移动一个位置。
  3. 更新 _finish_end,删除最后一个元素。

这些关键代码片段涵盖了 Vector 类的核心功能,包括元素的添加、删除、扩容等操作。

判空函数 empty()

cppCopy codebool empty() const {
    return _start == _finish;
}
  • 作用: 判定容器是否为空。
  • 解释: _start_finish 是迭代器,它们指向容器的起始和元素结束位置。如果它们相等,说明容器为空,返回 true;否则返回 false

打印函数 Print()

cppCopy codevoid Print() {
    if (empty()) {
        std::cout << "容器为空." << std::endl;
        return;
    }
    std::cout << "容器元素: ";
    for (size_t i = 0; i < size(); i++) {
        std::cout << _start[i] << "  ";
    }
    std::cout << std::endl;
}
  • 作用: 打印容器中的元素。
  • 解释:
    • 首先,通过调用 empty() 判定容器是否为空。
    • 如果为空,输出提示信息。
    • 否则,使用循环遍历容器中的元素,并输出到控制台。

计算元素个数函数 size()

cppCopy codesize_t size() const {
    return _finish - _start;
}
  • 作用: 获取容器中元素的个数。
  • 解释: _finish_start 分别指向元素结束和容器起始位置,通过它们的差值可以得到容器中元素的个数。

计算容器长度函数 capacity()

cppCopy codesize_t capacity() const {
    return _end - _start;
}
  • 作用: 获取容器的总长度(即容器的总容量)。
  • 解释: _end_start 分别指向容器的末尾和起始位置,通过它们的差值可以得到容器的总长度,即容器的总容量。

这些函数提供了对容器状态的查询和展示功能,使用户能够更方便地了解容器的结构和内容。在实际应用中,这些操作通常是基础而重要的。

完整代码:

/*************************************************************************
        > File Name: Vector.cpp
        > Author:
        > Mail:
        > Created Time: Sun Nov  5 17:40:52 2023
 ************************************************************************/

#include <iostream>
#include <cassert>
#include <string>
using namespace std;

#define BEGINS(x) namespace x{
#define ENDS(x)}

template <typename T>
class Vector {
public:
    typedef T value_type;
    typedef T* iterator;

    Vector() : _start(nullptr), _finish(nullptr), _end(nullptr) {}

    size_t size() const {
        return _finish - _start;
    }

    size_t capacity() const {
        return _end - _start;
    }

    void push_back(const value_type &x) {
        if (capacity() == 0 || capacity() == size()) {
            reserve((capacity() == 0) ? 1 : capacity() * 2);
        }
        *_finish = x;
        ++_finish;
    }

    void pop_back() {
        if (!empty()) {
            --_finish;
            cout << "弹出元素: " << *_finish << endl;
        } else {
            cout << "容器为空,无法弹出元素." << endl;
        }
    }

    void insert(const value_type &x, const size_t &pos) {
        if (pos > size()) {
            cout << "越界: 无法在指定位置插入元素." << endl;
            return;
        }
        if (capacity() == 0) {
            reserve(1);
            *_finish = x;
            ++_finish;
        } else if (size() == capacity()) {
            size_t size1 = size();
            size_t cap = capacity();
            value_type* tmp = new value_type[2 * capacity()]();
            for (size_t i = 0; i < pos; i++) {
                tmp[i] = _start[i];
            }
            tmp[pos] = x;
            for (size_t i = pos; i < size1; i++) {
                tmp[i + 1] = _start[i];
            }
            delete[] _start;
            _start = tmp;
            _finish = _start + size1 + 1;
            _end = _start + 2 * cap;
        } else {
            for (int i = size(); i > pos; i--) {
                _start[i] = _start[i - 1];
            }
            _start[pos] = x;
            _finish = _start + size() + 1;
        }
    }

    void erase(const size_t &pos) {
        if (pos >= 0 && pos < size()) {
            iterator begin = _start + pos;
            while (begin != _finish) {
                *begin = *(begin + 1);
                ++begin;
            }
            --_finish;
            //--_end;
        } else {
            cout << "越界: 无法删除指定位置的元素" << endl;
        }
    }

    void Print() {
        if (empty()) {
            cout << "容器为空." << endl;
            return;
        }
        cout << "容器元素: ";
        for (size_t i = 0; i < size(); i++) {
            cout << _start[i] << "  ";
        }
        cout << endl;
    }

    void reserve(size_t newCapacity) {
        value_type* tmp = new value_type[newCapacity]();
        size_t size1 = size();
        if (_start) {
            for (size_t i = 0; i < size1; i++) {
                tmp[i] = _start[i];
            }
        }
        delete[] _start;
        _start = tmp;
        _finish = _start + size1;
        _end = _start + newCapacity;
    }

    bool empty() const {
        return _start == _finish;
    }

private:
    iterator _start;
    iterator _finish;
    iterator _end;
};


BEGINS(test3)

int main() {
  Vector<string> ve; //Vector<string> ve; 中的string是模板类型Vector中的元素类型
    cout << "按1压入数据" << endl;
    cout << "按2插入数据" << endl;
    cout << "按3弹出数据" << endl;
    cout << "按4删除数据" << endl;
    cout << "按5查看现有数据" << endl;
    cout << "按111结束" << endl;
    int a, y;
    string x;
    while (true) {
        cin >> a;
        if (a == 111) break;
        switch (a) {
            case 1:
                cout << "请输入要压入的元素: ";
                cin >> x;
                ve.push_back(x);
                break;
            case 2:
                cout << "请输入要插入的元素和位置 (元素 位置): ";
                cin >> x >> y;
                ve.insert(x, y);
                break;
            case 3:
                ve.pop_back();
                break;
            case 4:
                cout << "请输入要删除的位置: ";
                cin >> y;
                ve.erase(y);
                break;
            case 5:
                ve.Print();
                break;
        }
    }
    return 0;
}
ENDS(test3)


int main() {
    test3::main();
    return 0;
}
  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值