两个注意点:
1)底层内存分配采用 new 和 delete,非 stl 书中所示
2)移动元素为集体后移,并非原书中拆解后移(原书移动方式原因未知)
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
template<class T>
class MyVector{
protected:
T* start;
T* finish;
T* end_of_storage;
void fill_initialize(size_t n, const T& value){
// 一旦使用 malloc,每次 ++ 都是一个字节,计算起来非常麻烦,使用new,每次++都是一个元素大小,更具有通用性
// start = (T *)malloc(sizeof(T)*n); // 申请n个T类型
// finish = start + n * sizeof(T);
start = new T[n];
memset(start, value, n);
finish = start + n;
end_of_storage = finish;
}
public:
MyVector():start(0), finish(0), end_of_storage(0){
}
MyVector(size_t n, const T& value){
fill_initialize(n, value);
}
~MyVector(){
if (start != NULL){
delete [] start;
}
}
T& operator[](size_t pos){
return *(start + pos);
}
T* begin(){
return start;
}
T* end(){
return finish;
}
size_t size(){
return size_t(end() - begin()); // 指针是元素级别移动,而并非字节级别移动
}
size_t capacity(){
return size_t(end_of_storage - begin());
}
T& front(){
return *begin();
}
T& back(){
return *(finish-1);
}
void push_back(const T& value){
insert(end(), 1, value);
}
void pop_back(){
erase(end() - 1);
}
// 在指定位置插入 n 个元素
void insert(T *position, size_t n, const T& x){
if(n != 0){
// 元素空间够用
if(size_t(end_of_storage-finish) >= n){
T *before = finish - 1;
T *after = finish + n - 1;
// 元素后移
while (before >= position){
*after = *before;
after--;
before--;
}
finish += n; // 往后n个
// 从插入点开始填入新值
for (int i = 1; i <= n; ++i) {
*position = x;
position++;
}
}else{
// 元素空间不够用
// 两个长度选一: 原长度两倍,或者原长度+插入元素个数
size_t len = max(capacity()*2, capacity()+n);
T* new_start = new T[len];
T* new_finish = new_start;
// 将原有元素复制
T* temp = start;
while (temp != position){ // 复制插入之前的
*new_finish = *temp;
temp++;
new_finish++;
}
// 插入的放入新空间
for (int i = 1; i <= n; ++i) {
*new_finish = x;
new_finish++;
}
// 将后续的放入新空间
while (temp != finish){
*new_finish = *temp;
temp++;
new_finish++;
}
// 释放原空间
delete [] start;
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
}
}
// 清除某一段元素
T* erase(T* op, T*ed){
T *op_save = op;
size_t len = ed - op;
// 将后续元素进行拷贝
T* temp = ed;
while (temp != finish){
*op = *temp;
op++;
temp++;
}
finish -= len;
return op_save;
}
// 清除pos位置的元素
T *erase(T *pos){
return erase(pos, pos+1);
}
void resize(size_t n, const T& x){
// 变大
if(n > size()){
insert(end(), n-size(), x);
}else{
// 变小
erase(begin() + n, end());
}
}
void resize(size_t n){
resize(n, T());
}
void clear(){
erase(begin(), end());
}
};
template<class T>
void PrintVector(MyVector<T>& v){
cout << "v.size(): " << v.size() << ", v.capacity():" << v.capacity() << endl;
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
}
void TestInt(){
MyVector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
PrintVector(v);
v.pop_back();
v.pop_back();
PrintVector(v);
v.insert(v.begin(), 6, 6);
PrintVector(v);
v.insert(v.begin() + 2, 3, 3);
PrintVector(v);
v.erase(v.begin()+1, v.end()-2);
PrintVector(v);
v.resize(5);
PrintVector(v);
v.resize(10, 0);
PrintVector(v);
}
class Student{
public:
string name;
int age;
Student(string name, int age){
this->name = name;
this->age = age;
}
Student(){
}
};
void PrintVectorClass(MyVector<Student> &v){
cout << "v.size(): " << v.size() << ", v.capacity():" << v.capacity() << endl;
for (int i = 0; i < v.size(); ++i) {
cout << v[i].name << " " << v[i].age << endl;
}
}
void TestClass(){
MyVector<Student> v;
Student s1("a", 1);
Student s2("b", 2);
Student s3("c", 3);
Student s4("d", 4);
Student s5("e", 5);
Student s6("f", 6);
v.push_back(s1);
v.push_back(s2);
v.push_back(s3);
v.push_back(s4);
v.push_back(s5);
v.push_back(s6);
PrintVectorClass(v);
v.pop_back();
v.pop_back();
v.pop_back();
PrintVectorClass(v);
Student s7("g", 7);
Student s8("h", 8);
Student s9("i", 9);
Student s10("j", 10);
v.push_back(s7);
v.insert(v.end()-2, 1, s8);
v.insert(v.end()-3, 1, s9);
v.insert(v.end()-4, 1, s10);
PrintVectorClass(v);
v.erase(v.begin()+3, v.begin()+5);
PrintVectorClass(v);
v.insert(v.begin(), 2, s4);
PrintVectorClass(v);
v.resize(5);
PrintVectorClass(v);
v.resize(10);
PrintVectorClass(v);
}
int main(){
TestClass();
// TestInt();
}
有任何疑惑,欢迎探讨