2011-01-14 28 views

cevap

30

Tipik C kodu şuna benzer: Maalesef

oldMem = realloc(oldMem, newSize); 
if(!oldMem) 
{ 
    // handle error 
} 

: realloc sıfır döndürür ama eski bellek hala geçerlidir ardından başarısız olursa, bu tipik kullanım bellek sızıntısına neden olduğunu

void* newMem = realloc(oldMem, newSize); 
if(!newMem) 
{ 
    // handle error 
} 

oldMem = newMem; 

Not çok yaygındır; Ayrıca, C++ vektörü/listesi hakkında özel bir şey olmadığını unutmayın. Benzer yapılar C dilinde uygulanabilir, sadece sözdizimi (ve hata işleme) farklı görünür. Örneğin, C.

+0

serin vay, C++ eşdeğer Böylece whats? Örneğin. malloc = yeni, ücretsiz = sil, realloc =? – Kaije

+0

@ user: Eşdeğerleriniz yanlış. Bunlar: malloc = vektör :: vektör, serbest = vektör :: temizle, realloc = vektör :: yeniden boyutlandır. – ybungalobill

+2

@ybungalobill, um ... 'vektör :: temizle() '' özgür' için hiçbir şekilde gerçek anlamda değildir. –

23

için std :: vektörünün LodePNG's analoguna bakınız. C gibi birçok proje bir vektör benzeri API uygular. Dinamik diziler yaygın bir ihtiyaçtır, bellek yönetimini mümkün olduğunca soyutlamak güzeldir. onlar vector üzerinde işlem çeşitli API işlev çağrıları olurdu Sonra

typedef struct dynamic_array_struct 
{ 
    int* data; 
    size_t capacity; /* total capacity */ 
    size_t size; /* number of elements in vector */ 
} vector; 

:

int vector_init(vector* v, size_t init_capacity) 
{ 
    v->data = malloc(init_capacity * sizeof(int)); 
    if (!v->data) return -1; 

    v->size = 0; 
    v->capacity = init_capacity; 

    return 0; /* success */ 
} 

Sonra tabii ki, push_back için fonksiyonları ihtiyaç , insert, resize gibi tipik bir C uygulaması görünebilir realloc'u arayarak, sizecapacity'u aşarsa Bir yeniden tahsis gerektiğinde

vector_resize(vector* v, size_t new_size); 

vector_push_back(vector* v, int element); 

Genellikle, capacity her zaman yeniden tahsis önlemek için iki katına çıkarılır. Bu genellikle, std::vector tarafından dahili olarak kullanılan aynı stratejidir, genellikle C++ nesnesi yapısı/imhası nedeniyle realloc numaralı telefonu arayamaz. Bunun yerine, std::vector, yeni bir arabellek tahsis edebilir ve daha sonra yapıyı/taşı kopyala (yeni yerleşimi new kullanarak) yeni arabelleğe oluşturur.

C'deki gerçek bir vektör uygulaması, int yerine öğeler olarak void* işaretçileri kullanabilir, bu nedenle kod daha geneldir. Her neyse, bu tür şeyler çok sayıda C projesinde uygulanmaktadır. Örnek bir vektör uygulaması için bakınız: http://codingrecipes.com/implementation-of-a-vector-data-structure-in-c C.

+0

Burada yapınızın veri değişkeni için bir işaretçi oluşturuyor gibi görünüyorsun. vektör uygulamaları çevrimiçi Ben yapının veri değişkeni bir çift işaretçi tarafından tutulduğunu gördüm. Bu iki yol arasındaki fark nedir? – Kai

+0

Link bozuk, bkz. Https://gist.github.com/EmilHernvall/953968/0fef1b1f826a8c3d8cfb74b2915f17d2944ec1d0 ne için popüler bir uygulama gibi görünüyor –

8

Uygulama için gerekli üyeleri tutacak bir yapı tanımlayarak gizlemeye başlayacaklardır. Daha sonra yapının içeriğini manipüle edecek bir fonksiyon grubu sağlayın. Böyle

şey: Bunların ötesinde

typedef struct vec 
{ 
    unsigned char* _mem; 
    unsigned long _elems; 
    unsigned long _elemsize; 
    unsigned long _capelems; 
    unsigned long _reserve; 
}; 

vec* vec_new(unsigned long elemsize) 
{ 
    vec* pvec = (vec*)malloc(sizeof(vec)); 
    pvec->_reserve = 10; 
    pvec->_capelems = pvec->_reserve; 
    pvec->_elemsize = elemsize; 
    pvec->_elems = 0; 
    pvec->_mem = (unsigned char*)malloc(pvec->_capelems * pvec->_elemsize); 
    return pvec; 
} 

void vec_delete(vec* pvec) 
{ 
    free(pvec->_mem); 
    free(pvec); 
} 

void vec_grow(vec* pvec) 
{ 
    unsigned char* mem = (unsigned char*)malloc((pvec->_capelems + pvec->_reserve) * pvec->_elemsize); 
    memcpy(mem, pvec->_mem, pvec->_elems * pvec->_elemsize); 
    free(pvec->_mem); 
    pvec->_mem = mem; 
    pvec->_capelems += pvec->_reserve; 
} 

void vec_push_back(vec* pvec, void* data, unsigned long elemsize) 
{ 
    assert(elemsize == pvec->_elemsize); 
    if (pvec->_elems == pvec->_capelems) { 
     vec_grow(pvec); 
    } 
    memcpy(pvec->_mem + (pvec->_elems * pvec->_elemsize), (unsigned char*)data, pvec->_elemsize); 
    pvec->_elems++;  
} 

unsigned long vec_length(vec* pvec) 
{ 
    return pvec->_elems; 
} 

void* vec_get(vec* pvec, unsigned long index) 
{ 
    assert(index < pvec->_elems); 
    return (void*)(pvec->_mem + (index * pvec->_elemsize)); 
} 

void vec_copy_item(vec* pvec, void* dest, unsigned long index) 
{ 
    memcpy(dest, vec_get(pvec, index), pvec->_elemsize); 
} 

void playwithvec() 
{ 
    vec* pvec = vec_new(sizeof(int)); 

    for (int val = 0; val < 1000; val += 10) { 
     vec_push_back(pvec, &val, sizeof(val)); 
    } 

    for (unsigned long index = (int)vec_length(pvec) - 1; (int)index >= 0; index--) { 
     int val; 
     vec_copy_item(pvec, &val, index); 
     printf("vec(%d) = %d\n", index, val); 
    } 

    vec_delete(pvec); 
} 

onlar fonksiyon grubu için vec * yerine boşluk * kullanarak kapsülleme ulaşmak ve aslında içinde tanımlayarak kullanıcıdan yapı tanımını saklanırdın başlık yerine işlev grubunu içeren C modülü. Ayrıca, özel olarak düşünmeyi düşündüğünüz işlevleri, başlıktan çıkartarak ve yalnızca C modülünde sadece prototipleme yaparak gizlerler.

struct vc_vector { 
    size_t count; 
    size_t element_size; 
    size_t reserved_size; 
    char* data; 
    vc_vector_deleter* deleter; 
}; 

... 

vc_vector* vc_vector_create_copy(const vc_vector* vector) { 
    vc_vector* new_vector = vc_vector_create(vector->reserved_size/vector->count, 
              vector->element_size, 
              vector->deleter); 
    if (unlikely(!new_vector)) { 
    return new_vector; 
    } 

    if (memcpy(vector->data, 
      new_vector->data, 
      new_vector->element_size * vector->count) == NULL) { 
    vc_vector_release(new_vector); 
    new_vector = NULL; 
    return new_vector; 
    } 

    new_vector->count = vector->count; 
    return new_vector; 
} 

Kullanmak için:

+0

Bunu 30 dakika içinde yazdı, garanti yok. –

1

Sen uygulama vc_vector görebilirsiniz

vc_vector* v1 = vc_vector_create(0, sizeof(int), NULL); 
for (int i = 0; i < 10; ++i) { 
    vc_vector_push_back(v1, &i); 
} 

// v1 = 0 1 2 3 4 5 6 7 8 9 

vc_vector* v2 = vc_vector_create_copy(v1); 

// v2 = 0 1 2 3 4 5 6 7 8 9 (copy of v1) 

// to get pointer to int: 

const int* v2_data = vc_vector_data(v1);