C (++) путаница с маллок - PullRequest
       15

C (++) путаница с маллок

3 голосов
/ 23 февраля 2010

Я просто не буду больше выделять память для массивов в C и в основном в C ++. Я искал примеры, но для меня там нет никаких полезных, по крайней мере, так кажется.

Итак, если у меня есть typedef вот так:

typedef struct
{
int x;
int y;
} Coordinate;

Coordinate* myList;

И у меня тоже есть массив типа Coordinate, как мне динамически добавлять к нему элементы. Все, что я знаю, это то, что я должен использовать malloc и позже free в C и new / delete в C ++. (Маллок пугает меня до чертиков)

Так что я стремился к такой функции:

void AddSomething ( int x, int y )
{
// myList malloc/new magic here
}

Мой вопрос:

  • Как должна выглядеть строка, которая выделяет новую память для myList, а затем добавляет в нее новый элемент? Не могли бы вы показать мне рабочий пример для C и C ++?

  • Как именно работает malloc в C? Есть некоторые вещи, с которыми я не знаком (есть какой-то указатель перед функцией, и для переменной, которая выделяется, устанавливается malloc возвращаемое значение)

Ответы [ 7 ]

14 голосов
/ 23 февраля 2010

Используйте вектор, чтобы сделать работу.

#include <vector>

typedef struct
{
int x;
int y;
} Coordinate;

std::vector<Coordinate> coordinates;

Coordinate newCoord;
newCoord.x = 1;
newCoord.y = 1;

coordinates.push_back(newCoord);

Дополнительная информация: Для понимания malloc / free и new / delete вы можете прочитать главу

13: создание динамических объектов

у Брюса Экелса Мышление C ++ Том 1 . Это книга, которую можно скачать бесплатно.

5 голосов
/ 23 февраля 2010

Для C следующее создаст список, содержащий одну координату:

myList = malloc(sizeof(Coordinate));

Если вы хотите выделить массив размером n, выполните следующие действия:

myList = malloc(n * sizeof(Coordinate));

В C ++ код для массива размера n выглядит следующим образом:

myList = new Coordinate[n];

В случае C ++ ваш класс должен иметь конструктор по умолчанию, который класс Coordinate имеет неявно. Однако для C ++ я настоятельно рекомендую использовать std::vector<Coordinate> вместо массива, управляемого вручную.

Кроме того, вы можете использовать malloc() для выделения памяти также и в C ++, но он выделяет только необработанную память, тогда как использование new также вызовет вызов конструктора (ов). В случае вашей структуры нет разницы, так как это структура POD и не требует конструктора. Также имейте в виду, что если вы выделяете память в C ++ с помощью malloc(), вы должны использовать free() для ее освобождения; если вы используете new, вам нужно использовать delete - их смешивание может привести к очень интересным результатам, которые не забавны для отладки. С new вы также должны убедиться, что вы соответствуете правильному типу вызова. Все, что создано с помощью new, необходимо очистить с помощью delete, а все, что создано с использованием массива new, как в моем примере выше, необходимо удалить с помощью delete[].

.
3 голосов
/ 23 февраля 2010

Для любого вопроса, подобного этому, первый ответ должен быть другим вопросом. В частности, есть ли действительно веская причина, по которой вы не можете использовать std::vector? Если вы действительно, действительно, абсолютно не можете , это то, что нужно сделать.

В противном случае ваш единственный реальный выбор - написать (еще одну) имитацию std::vector. Хотя я не знаю вас лично, опыт показывает, что то, что вы пишете, вероятно, будет не таким хорошим.

1 голос
/ 23 февраля 2010

Маллок пугает меня до чертиков

Быть осторожным с управляемой рукой динамической памятью - хорошая идея - есть много шансов сделать ошибки, делая это; трудно отлаживать ошибки --- но не нужно пугаться.

То, что делает malloc, запрашивает у ОС кусок памяти, по крайней мере, НА ЭТОМ большом . Это все. Вы должны использовать указатели для отслеживания этого, потому что компилятор не знает, какую память выберет ОС, и поэтому не может подключить имя переменной к месту во время компиляции.

То, что делает free, это сообщает ОС, я с ЭТОЙ памятью покончил и больше не буду ее использовать Это все

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

Итак, чтобы успешно использовать динамическое размещение, вы должны

  • Спросите, какая память вам нужна * за 1028 * до вы пытаетесь ее использовать и проверяете, действительно ли вы ее получили (операционная система может сказать: "Нет, вы не можете ее получить." *
  • Убедитесь, что вы инициализируете его (либо напишите правильный конструктор на c ++, либо управляйте им самостоятельно на c)
  • Не забывайте об этом.
  • Убедитесь, что вы управляете любой необходимой очисткой, прежде чем возвращать ее (деструкторы в c ++, вручную в c). Это, наверное, самая трудная часть всего бизнеса.
  • Никогда не используйте память после , когда вы вернули ее
0 голосов
/ 23 февраля 2010
#include <stdlib.h>

struct
{
int x;
int y;
} Coordinate;

Coordinate* myList = 0;

int myListLength = 0;  // initialize myListLength to size of myList

void AddSomething ( int x, int y )
{
    int i;
    // malloc returns a void pointer, so we cast it to be a Coordinate *
    Coordinate* newList = (Coordinate*)malloc(sizeof(Coordinate)*(myListLength+1));
    for(i=0; i < myListLength; ++i) {
        newList[i] = myList[i];
    }
    newList[myListLength].x = x;
    newList[myListLength].y = y;
    if(myList)
        free(myList);
    myList = newList;
    ++myListLength;
 }

Обратите внимание, что гораздо лучше использовать std :: vector, если вы можете.

0 голосов
/ 23 февраля 2010
  • Как должна выглядеть строка, которая выделяет новую память для myList, а затем добавляет в нее новый элемент? Не могли бы вы показать мне рабочий пример для C и C ++?

На самом деле есть две разные опции: Вы можете создать массив из Coordinate объектов, используя:

Coordinate *list = new Coordinate[ 42 ]; // list can hold at most 42 objects

Или используйте связанный список, который, конечно, потребует от вас изменить определение вашего Coordinate типа данных:

typedef Coordinate_t {
    int x, y;
    Coordinate_t *next;
};

Вставка в связанный список немного сложнее.

Конечно, если вы используете C, вы не можете использовать оператор new, но вместо этого вам придется использовать malloc:

Coordinate *list = malloc(*list * 42); /* list can hold at most 42 objects */
  • Как именно работает malloc в C? Есть некоторые вещи, с которыми я не знаком (есть некоторый указатель перед функцией, и для переменной, которая выделяется, устанавливается возвращаемое значение malloc)

Функция выделения использует некоторый специфичный для ОС API для запроса некоторой памяти из свободного хранилища (и, следовательно, это зависит от реализации). E.g: В * nix используется системный API с именем sbrk и друзья.

0 голосов
/ 23 февраля 2010

C malloc просто выделяет память, но не "создает" объект. В C ++ вы обычно используете new, который выделяет и создает объект. Основное отличие - new вызывает конструктор после выделения оперативной памяти. malloc - просто «тупой» менеджер памяти, но он может работать лучше в определенных конкретных случаях, когда вам нужна нетипизированная необработанная память.

И new, и malloc "возвращают" указатель. Указатель - это адрес. Так что это форма обоих, они являются выражениями присваивания.

Coordinate * notObject = (Coordinate*)malloc(sizeof(Coordinate));
Coordinate * object = new Coordinate();

Обратите внимание, malloc возвращает void *, поэтому вы должны разыграть его. new набрано, поэтому кастинг не требуется.

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