-
Notifications
You must be signed in to change notification settings - Fork 3
/
Vector.h
170 lines (169 loc) · 3.99 KB
/
Vector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#pragma once
#include <cstdlib>
#include <type_traits>
namespace ds
{
template <typename K>
class Vector
{
const static int InitialCap = 8;
const static bool NonTrivial = !std::is_trivially_copyable<K>::value || !std::is_trivially_destructible<K>::value;
void realloc(int newCap)
{
//realloc:尝试追加内存;失败则新申请内存并bitwise拷贝
arr = (K*)std::realloc(arr, sizeof(K) * newCap);
cap = newCap;
}
void expand()
{
if (siz == cap)
realloc(cap << 1);
}
static void destruct(K *first, K *last)
{
if (NonTrivial)
for (; first != last; ++first)
first->~K();
}
static void destruct(K *pos) { pos->~K(); }
template <typename ...Args>
static void construct(K *pos, Args &&...args) { new(pos) K(std::forward<Args>(args)...); }
static int calc(int len)
{
int cap = InitialCap;
for (; cap < len; cap <<= 1);
return cap;
}
protected:
int siz = 0;
int cap = 0;
K * arr = nullptr;
static void mov(K *dest, const K *first, const K *last) //放弃原来的
{
memmove(dest, first, (last - first) * sizeof(K));
}
static void cpy(K *dest, const K *first, const K *last) //保留原来的
{
if (NonTrivial)
for (; first != last; ++dest, ++first)
new(dest) K(*first);
else
memcpy(dest, first, (last - first) * sizeof(K));
}
public:
void push_back(K key)
{
expand();
construct(arr + siz++, std::move(key));
}
void add_all(const Vector &rhs)
{
reserve(siz + rhs.siz);
cpy(arr + siz, rhs.begin(), rhs.end());
siz += rhs.siz;
}
void resize(int nSize)
{
if (nSize == siz)
return;
if (siz < nSize)
{
reserve(calc(nSize));
for (K *cur = arr + siz, *last = arr + nSize; cur != last; ++cur)
construct(cur, K());
}
else
destruct(arr + nSize, arr + siz);
siz = nSize;
}
void pop_back() { destruct(arr + --siz); }
void erase(int pos, int cnt = 1)
{
cnt = min(siz - pos, cnt);
if (!cnt)
return;
destruct(arr + pos, arr + pos + cnt);
mov(arr + pos, arr + pos + cnt, arr + siz);
//注意到,对于类类型会产生siz和siz-1位置两个bit完全一致的版本
//但是这并不会有什么问题,因为不可能再对siz位置的对象调用析构函数
siz -= cnt;
}
void insert(int pos, K key) //insert and be there
{
expand();
mov(arr + pos + 1, arr + pos, arr + siz);
construct(arr + pos, std::move(key));
}
void reserve(int nCap)
{
nCap = calc(nCap);
if (nCap > cap)
realloc(nCap);
}
K *begin() { return arr; }
K *end() { return arr + siz; }
const K *begin() const { return arr; }
const K *end() const { return arr + siz; }
K &front() { return *arr; }
K &back() { return *(arr + siz - 1); }
const K &front() const { return *arr; }
const K &back() const { return *(arr + siz - 1); }
bool empty() const { return siz == 0; }
int size() const { return siz; }
int capacity() const { return cap; }
K &operator[](int pos) { return arr[pos]; }
const K &operator[](int pos) const { return arr[pos]; }
Vector(int size = 0)
: siz(size), cap(max(calc(siz),InitialCap)), arr((K *)malloc(cap * sizeof(K)))
{
for (K *cur = arr, *last = arr + siz; cur != last; ++cur)
construct(cur, K());
}
void swap(Vector &rhs) noexcept
{
std::swap(arr, rhs.arr);
std::swap(siz, rhs.siz);
std::swap(cap, rhs.cap);
}
Vector &operator=(Vector rhs)
{
swap(*this, rhs);
return *this;
}
Vector(const Vector &rhs) : arr(nullptr)
{
reserve(rhs.siz);
siz = rhs.siz;
cpy(arr, rhs.begin(), rhs.end());
}
Vector &operator=(Vector &&rhs) noexcept
{
if (this != &rhs)
{
Vector tmp(std::move(rhs));
swap(tmp);
}
return *this;
}
Vector(Vector &&rhs) noexcept
{
arr = rhs.arr;
cap = rhs.cap, siz = rhs.siz;
rhs.arr = nullptr;
}
Vector(const std::initializer_list<K> &rhs)
{
reserve(rhs.size());
siz = rhs.size();
cpy(arr, rhs.begin(), rhs.end());
}
~Vector()
{
if (arr)
{
destruct(arr, arr + siz);
free(arr);
}
}
};
}