3
3
// This is internal headerfile to be included by vector.h only
4
4
5
5
#include < new.h>
6
+ #include < stdio.h>
6
7
#include < stdlib.h>
7
8
#include < string.h>
8
9
#include < vector.h>
9
10
10
11
namespace std {
11
12
12
- static std::size_t next_power2 (std::size_t size) {
13
- // assumes no overflow
14
- std::size_t p = 1 ;
15
- while (p && p < size)
16
- p <<= 1 ;
17
- return p;
18
- }
13
+ template <typename T>
14
+ vector<T>::vector() : _data(NULL ), _capacity(0 ), _size(0 ) {}
19
15
20
16
template <typename T>
21
- vector<T>::vector() : _data(NULL ), _capacity(0 ), _size(0 ) {
22
- resize_capacity (1 );
17
+ vector<T>::vector(std::size_t size) : _data(NULL ), _capacity(0 ), _size(0 ) {
18
+ reserve (size);
19
+ // initializing the members
20
+ for (std::size_t i = 0 ; i < size; i++) {
21
+ new (_data + i) T (); // default constructor
22
+ }
23
+ _size = size;
23
24
}
24
25
25
26
template <typename T>
26
27
vector<T>::vector(std::size_t size, const T &_default)
27
- : _data(NULL ), _capacity(0 ), _size(size) {
28
- resize_capacity (size);
28
+ : _data(NULL ), _capacity(0 ), _size(0 ) {
29
+ reserve (size);
30
+ // initializing the members
29
31
for (std::size_t i = 0 ; i < size; i++) {
30
- this -> _data [i] = _default;
32
+ new ( _data + i) T ( _default); // copy constructor
31
33
}
34
+ _size = size;
32
35
}
33
36
34
37
template <typename T>
35
- vector<T>::vector(const vector<T> &o)
36
- : _data(NULL ), _capacity(0 ), _size(o._size) {
37
- resize_capacity (o._capacity );
38
- std::memcpy (_data, o._data , _capacity * sizeof (T));
38
+ vector<T>::vector(const vector<T> &o) : _data(NULL ), _capacity(0 ), _size(0 ) {
39
+ reserve (o._size );
40
+ // initializing the members
41
+ for (std::size_t i = 0 ; i < o._size ; i++) {
42
+ new (_data + i) T (o._data [i]); // copy constructor
43
+ }
44
+ _size = o._size ;
39
45
}
40
46
41
47
template <typename T> vector<T> &vector<T>::operator =(const vector<T> &o) {
42
- resize_capacity (o._capacity );
43
- _size = o._size ;
44
- std::memcpy (_data, o._data , _capacity * sizeof (T));
48
+ resize (o._size );
49
+ // re-initialize the members
50
+ for (std::size_t i = 0 ; i < o._size ; i++) {
51
+ _data[i] = o._data [i]; // assignment operator
52
+ }
45
53
return *this ;
46
54
}
47
55
48
- template <typename T> vector<T>::~vector () { delete[] _data; }
56
+ template <typename T> vector<T>::~vector () {
57
+ clear ();
58
+ reserve (0 );
59
+ }
49
60
50
- template <typename T> typename vector<T>::iterator vector<T>::begin() {
51
- return this ->_data ;
61
+ template <typename T> void vector<T>::reserve(std::size_t new_capacity) {
62
+ if (new_capacity < _size)
63
+ new_capacity = _size; // never reserve less than size
64
+ if (new_capacity == _capacity)
65
+ return ; // resize not needed
66
+
67
+ const std::size_t new_capacity_size = (new_capacity) * sizeof (T);
68
+
69
+ // make a copy of array and move _data pointer.
70
+ _data = (T *)std::realloc (_data, new_capacity_size);
71
+ _capacity = new_capacity;
52
72
}
53
73
54
- template <typename T> typename vector<T>::iterator vector<T>::end() {
55
- return this ->_data + this ->_size ;
74
+ template <typename T> void vector<T>::resize(const std::size_t new_size) {
75
+ if (_size < new_size) {
76
+ reserve (new_size);
77
+ for (std::size_t i = _size; i < new_size; i++) {
78
+ new (_data + i) T (); // default constructor
79
+ }
80
+ _size = new_size;
81
+ } else {
82
+ for (std::size_t i = new_size; i < _size; i++) {
83
+ _data[i].~T (); // explicit destructor call
84
+ }
85
+ _size = new_size;
86
+ // not reducing the allocated capacity.
87
+ }
56
88
}
57
89
58
90
template <typename T>
59
- typename vector<T>::const_iterator vector<T>::begin() const {
60
- return this ->_data ;
91
+ void vector<T>::resize(const std::size_t new_size, const T &_default) {
92
+ if (_size < new_size) {
93
+ reserve (new_size);
94
+ for (std::size_t i = _size; i < new_size; i++) {
95
+ new (_data + i) T (_default); // copy constructor
96
+ }
97
+ _size = new_size;
98
+ } else {
99
+ for (std::size_t i = new_size; i < _size; i++) {
100
+ _data[i].~T (); // explicit destructor call
101
+ }
102
+ _size = new_size;
103
+ // not reducing the allocated capacity.
104
+ }
61
105
}
62
106
63
- template <typename T>
64
- typename vector<T>::const_iterator vector<T>::end() const {
65
- return this ->_data + this ->_size ;
107
+ template <typename T> void vector<T>::push_back(const T &val) {
108
+ if (_size == _capacity) {
109
+ reserve (max (1 , _capacity * 2 ));
110
+ }
111
+ new (_data + (_size++)) T (val); // copy constructor
66
112
}
67
113
68
- template <typename T> void vector<T>::resize_capacity(std::size_t capacity) {
69
- // internal; assumes capacity to be power of 2
70
- // and will also make a copy of array and move _data pointer.
71
- // assumes size<=current_capacity and size<=new_capacity
72
- const std::size_t data_size =
73
- std::min (capacity, this ->_capacity ) * sizeof (T);
74
- T *_new_data = new T[capacity];
75
- if (!_new_data)
76
- return ; // malloc failed
77
- std::memcpy (_new_data, this ->_data , data_size);
114
+ template <typename T> void vector<T>::pop_back() {
115
+ if (!(_size > 0 )) {
116
+ return ;
117
+ }
78
118
79
- delete[] this ->_data ; // should be no-op if _data == NULL
80
- this ->_data = _new_data;
81
- this ->_capacity = capacity;
82
- }
119
+ _size--;
120
+ _data[_size].~T (); // explicit destructor call
83
121
84
- template <typename T> void vector<T>::clear() {
85
- // not reducing capacity for now
86
- this ->_size = 0 ;
122
+ // not reducing the allocated capacity.
87
123
}
88
124
89
- template <typename T> bool vector<T>::empty () const { return this -> _size == 0 ; }
125
+ template <typename T> void vector<T>::clear () { resize ( 0 ) ; }
90
126
91
- template <typename T> std:: size_t vector<T>::size() const {
92
- return this -> _size ;
127
+ template <typename T> typename vector<T>::iterator vector<T>::begin() {
128
+ return _data ;
93
129
}
94
130
95
- template <typename T> void vector<T>::push_back(const T &val) {
96
- if (this ->_size == this ->_capacity ) {
97
- resize_capacity (this ->_capacity * 2 );
98
- }
99
- this ->_data [this ->_size ++] = val;
131
+ template <typename T> typename vector<T>::iterator vector<T>::end() {
132
+ return _data + _size;
100
133
}
101
134
102
- template <typename T> void vector<T>::pop_back() {
103
- // not reducing the capacity for now
104
- if (this ->_size > 0 ) {
105
- this ->_size --;
106
- }
135
+ template <typename T>
136
+ typename vector<T>::const_iterator vector<T>::begin() const {
137
+ return _data;
107
138
}
108
139
109
- template <typename T> T &vector<T>::back() {
110
- return this ->_data [this ->_size - 1 ];
140
+ template <typename T>
141
+ typename vector<T>::const_iterator vector<T>::end() const {
142
+ return _data + _size;
111
143
}
112
144
113
- template <typename T> T & vector<T>::front () { return this -> _data [ 0 ] ; }
145
+ template <typename T> bool vector<T>::empty () const { return _size == 0 ; }
114
146
115
- template <typename T> T &vector<T>::at(std::size_t pos) {
116
- return this ->_data [pos];
117
- }
147
+ template <typename T> std::size_t vector<T>::size() const { return _size; }
148
+
149
+ template <typename T> T &vector<T>::back() { return _data[_size - 1 ]; }
150
+
151
+ template <typename T> T &vector<T>::front() { return _data[0 ]; }
152
+
153
+ template <typename T> T &vector<T>::at(std::size_t pos) { return _data[pos]; }
118
154
119
155
template <typename T> T &vector<T>::operator [](std::size_t pos) {
120
- return this -> _data [pos];
156
+ return _data[pos];
121
157
}
122
158
123
159
template <typename T> const T &vector<T>::operator [](std::size_t pos) const {
124
- return this -> _data [pos];
160
+ return _data[pos];
125
161
}
126
162
127
- } // namespace std
163
+ } // namespace std
0 commit comments