هذا هو تطبيق std::vector
مثل المصفوفة القابلة للنمو، ولكن في كود C89 العادي. والنتيجة هي نوع آمن وسهل الاستخدام ومصفوفة ديناميكية تحتوي على مجموعة مألوفة من العمليات.
إنه يعمل باستخدام نفس الخدعة التي يستخدمها العديد من المخصصات، وهي تخصيص بيانات أكثر قليلاً من المطلوب، واستخدام تلك المساحة الإضافية في المقدمة كمخزن للبيانات التعريفية. وبالتالي فإن أي ناقل غير فارغ يبدو هكذا في الذاكرة:
+-----------------+------+----------+---------+
| elem_destructor | size | capacity | data... |
+-----------------+------+----------+---------+
^
| user's pointer
حيث يتم إعطاء المستخدم مؤشرًا للعنصر الأول من data
. بهذه الطريقة يكون للكود وصول بسيط إلى البيانات التعريفية الضرورية، ولكن لا داعي للقلق على المستخدم بشأن هذه التفاصيل. إجمالي الحمل هو 2 * sizeof(size_t) + sizeof(void (*)(void *))
لكل ناقل.
للسماح بأن تكون التعليمات البرمجية عامة إلى الحد الأقصى، يتم تنفيذها كجميع وحدات الماكرو، وبالتالي فهي رأس فقط. الاستخدام بسيط:
/* 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 |
المدمر | 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); |