Ini adalah implementasi dari std::vector
seperti array yang dapat ditumbuhkan, tetapi dalam kode C89 biasa. Hasilnya adalah tipe array dinamis yang aman, mudah digunakan, dan memiliki serangkaian operasi yang familier.
Ia bekerja dengan menggunakan trik yang sama seperti banyak pengalokasi, yaitu mengalokasikan sedikit lebih banyak data daripada yang diminta, dan menggunakan bantalan tambahan di depan sebagai penyimpanan untuk meta-data. Jadi, vektor apa pun yang bukan nol akan terlihat seperti ini di memori:
+-----------------+------+----------+---------+
| elem_destructor | size | capacity | data... |
+-----------------+------+----------+---------+
^
| user's pointer
Dimana pengguna diberikan pointer ke elemen data
pertama. Dengan cara ini kode memiliki akses kecil ke metadata yang diperlukan, namun pengguna tidak perlu khawatir dengan detail ini. Total overhead adalah 2 * sizeof(size_t) + sizeof(void (*)(void *))
per vektor.
Untuk memungkinkan kode menjadi generik secara maksimal, kode ini diimplementasikan sebagai semua makro, dan dengan demikian hanya bersifat header. Penggunaannya sederhana:
/* if this is defined, then the vector will double in capacity each
* time it runs out of space. if it is not defined, then the vector will
* be conservative, and will have a capcity no larger than necessary.
* having this defined will minimize how often realloc gets called.
*/
#define CVECTOR_LOGARITHMIC_GROWTH
#include "cvector.h"
#include <stdio.h>
int main ( int argc , char * argv []) {
/* this is the variable that will store the array, you can have
* a vector of any type! For example, you may write float *v = NULL,
* and you'd have a vector of floats :-). NULL will have a size
* and capacity of 0. Additionally, vector_begin and vector_end will
* return NULL on a NULL vector. Alternatively, for clarity of writing
* you can use the cvector_vector_type macro to define a vector of a
* given type.
*/
cvector_vector_type ( int ) v = NULL ;
( void ) argc ;
( void ) argv ;
/* add some elements to the back */
cvector_push_back ( v , 10 );
cvector_push_back ( v , 20 );
cvector_push_back ( v , 30 );
cvector_push_back ( v , 40 );
/* remove an element by specifying an array subscript */
cvector_erase ( v , 2 );
/* remove an element from the back */
cvector_pop_back ( v );
/* print out some stats about the vector */
printf ( "pointer : %pn" , ( void * ) v );
printf ( "capacity: %lun" , cvector_capacity ( v ));
printf ( "size : %lun" , cvector_size ( v ));
/* iterator over the vector using "iterator" style */
if ( v ) {
int * it ;
int i = 0 ;
for ( it = cvector_begin ( v ); it != cvector_end ( v ); ++ it ) {
printf ( "v[%d] = %dn" , i , * it );
++ i ;
}
}
/* iterator over the vector standard indexing too! */
if ( v ) {
size_t i ;
for ( i = 0 ; i < cvector_size ( v ); ++ i ) {
printf ( "v[%lu] = %dn" , i , v [ i ]);
}
}
/* well, we don't have destructors, so let's clean things up */
cvector_free ( v );
return 0 ;
}
std::vector | cvector |
---|---|
std::vector<int> v | cvector(int) v |
Penghancur | cvector_free(v) |
v.at(3) | cvector_at(v, 3) |
v[3] | v[3] |
v.front() | cvector_front(v) |
v.back() | cvector_back(v) |
v.begin() | cvector_begin(v) |
v.end() | cvector_end(v) |
v.empty() | cvector_empty(v) |
v.size() | cvector_size(v) |
v.capacity() | cvector_capacity(v) |
v.shrink_to_fit() | cvector_shrink_to_fit(v) |
v.clear() | cvector_clear(v) |
v.insert(pos, value) | cvector_insert(v, pos, value) |
v.erase(v.begin() + 2) | cvector_erase(v, 2) |
v.push_back(value) | cvector_push_back(v, value) |
v.pop_back() | cvector_pop_back(v) |
v.reserve(new_cap) | cvector_reserve(v, new_cap) |
v.resize(count) | cvector_resize(v, count) |
v.swap(other) | cvector_swap(v, other) |
std::vector<int> other = v; | cvector(int) other; cvector_copy(v, other); |