Какая лучшая реализация c вектора C ++? - PullRequest
2 голосов
/ 19 октября 2011

Я изучал использование C поверх C ++, так как считаю его чище, и главное, чего мне не хватает, - это вектор, похожий на массив.

Какая лучшая реализация этого?

Я хочу просто иметь возможность вызывать что-то вроде vector_create, vector_at, vector_add и т. Д.

Ответы [ 6 ]

3 голосов
/ 19 октября 2011

Как насчет вектора, который вы хотите повторить? В конце концов, все сводится к следующему:

int *create_vector(size_t n) {
    return malloc(n * sizeof(int));
}

void delete_vector(int *v) {
    free(v);
}

int *resize_vector(int *v, size_t n) {
    return realloc(v, n * sizeof(int));
    /* returns NULL on failure here */
}

Вы могли бы обернуть все это в структуру, чтобы она тоже "знала свой размер", но вам придется делать это для каждого типа (здесь макросы?), Но это кажется немного бесполезным ... Возможно, что-то как это:

typedef struct {
    size_t size;
    int *data;
} int_vector;

int_vector *create_vector(size_t n) {
    int_vector *p = malloc(sizeof(int_vector));
    if(p) {
        p->data = malloc(n * sizeof(int));
        p->size = n;
    }
    return p;
}

void delete_vector(int_vector *v) {
    if(v) {
        free(v->data);
        free(v);
    }
}

size_t resize_vector(int_vector *v, size_t n) {
    if(v) {
        int *p = realloc(v->data, n * sizeof(int));
        if(p) {
            p->data = p;
            p->size = n;
        }
        return v->size;
    }
    return 0;
}

int get_vector(int_vector *v, size_t n) {
    if(v && n < v->size) {
        return v->data[n];
    }
    /* return some error value, i'm doing -1 here, 
     * std::vector would throw an exception if using at() 
     * or have UB if using [] */
    return -1;
}

void set_vector(int_vector *v, size_t n, int x) {
    if(v) {
        if(n >= v->size) {
            resize_vector(v, n);
        }
        v->data[n] = x;
    }
}

После чего вы можете сделать:

int_vector *v = create_vector(10);
set_vector(v, 0, 123);

Не знаю, кажется, это не стоит усилий.

1 голос
/ 19 октября 2011

Самым полным из известных мне способов создания полного набора типов утилит в C является GLib . Для ваших конкретных потребностей он обеспечивает g_array_new, g_array_append_val и так далее. См. Документация GLib Array .

0 голосов
/ 04 сентября 2013

Если вы можете умножить, вам не нужно использовать функцию vector_create (), когда у вас есть malloc () или даже calloc (). Вам просто нужно отслеживать два значения, указатель и выделенный размер, и отправлять два значения вместо одного в любую функцию, в которую вы передаете «вектор» (если функция действительно нуждается в указателе и размере, то есть) , malloc () гарантирует, что блок памяти является адресуемым как любой тип, поэтому присвойте ему void * возвращаемое значение, например, struct car * и индексируйте его []. Большинство процессоров обращаются к array[index] почти так же быстро, как variable, тогда как функция vector_at () может быть во много раз медленнее. Если вы храните указатель и размер вместе в структуре, делайте это только в не критичном ко времени коде, или вам придется индексировать с помощью vector.ptr[index]. Удалите пробел с помощью free ().

Сфокусируйтесь на написании хорошей оболочки вместо realloc (), которая перераспределяется только на каждую степень, например, 2 или 1,5. См. Ссылку пользователя Википедии на пользователя 786653 .

Конечно, calloc (), malloc () и realloc () могут потерпеть неудачу, если у вас закончилась память, и это еще одна возможная причина для выбора типа вектора. В C ++ есть исключения, которые автоматически завершают программу, если вы ее не ловите, а C - нет. Но это другое обсуждение.

0 голосов
/ 19 октября 2011

Apache Portable Runtime имеет приличный набор функций массива и все это C.

См. Краткое руководство по .

0 голосов
/ 19 октября 2011

Вместо того, чтобы идти по касательной в комментариях к @ ответу EvanTeran Я подумал, что отправлю здесь более длинный ответ.

Поскольку различные комментарии ссылаются на то, что на самом деле не так много смыслав попытке воспроизвести точное поведение std::vector, так как C не имеет шаблонов и RAII .

Однако может быть полезной реализация динамического массива , которая работает только с байтами.Очевидно, что это может быть использовано непосредственно для char* строк, но также может быть легко адаптировано для использования с любыми другими типами, если вы будете осторожны, чтобы умножить параметр размера на sizeof(the_type).

0 голосов
/ 19 октября 2011

Отсутствие функциональности шаблона в C делает невозможной поддержку вектороподобной структуры.Лучшее, что вы можете сделать, это определить «общую» структуру с помощью препроцессора, а затем «создать экземпляр» для каждого из типов, которые вы хотите поддерживать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...