массив вопросов по указателям, двойным указателям, malloc, realloc и new (чтобы установить рекорд) - PullRequest
2 голосов
/ 04 февраля 2011

Я догоняю указатели. Я записал несколько строк кода, чтобы протестировать различные способы динамического выделения 2-мерного массива (размещены внизу)

Мои вопросы следующие:

  1. Должен ли я использовать malloc в c ++ или new? Если я использую new, могу ли я использовать realloc?
  2. Когда мне следует использовать realloc? Каковы последствия использования его с точки зрения производительности и ошибок?
  3. Какой из примеров следует использовать из приведенных ниже примеров? Если ответ зависит от приложения, от чего он зависит?

Большое спасибо, Matt

#include <stdio.h>
#include <stdlib.h>

struct myObject
{
    int data;
    myObject(int i)
    {
        data = i;
    }
    myObject()
    {
        data = 0;
    }

};

int main(){
    int r = 7;
    int c = 6;

    printf("Objects using NEW===============================\n");
    //notice the triple pointer being assigned a new double pointer array
    myObject*** objectNew = new myObject** [r];

    for(int i=0;i<r;i++)
    {
        //objectNew is a 1D array of double pointers, however if we assign another layer of pointers, it becomes a 2D array of pointers to myObject
        objectNew[i] = new myObject* [c];
        for(int j=0;j<c;j++){
            objectNew[i][j] = new myObject(10*i+j);
            //notice that we dereference data (->)
            printf("objectNew[%2d][%2d]=%02d\n",i,j,objectNew[i][j]->data);
        }
    }
    delete objectNew;

    printf("Objects using NEW version 2===============================\n");
    //notice the triple pointer being assigned a new double pointer array
    myObject** objectNew2 = new myObject* [r];

    for(int i=0;i<r;i++)
    {
        //objectNew is a 1D array of double pointers, however if we assign another layer of pointers, it becomes a 2D array of pointers to myObject
        objectNew2[i] = new myObject [c];
        for(int j=0;j<c;j++){
            objectNew2[i][j] = myObject(10*i+j);
            //notice that we dereference data (->)
            printf("objectNew2[%2d][%2d]=%02d\n",i,j,objectNew2[i][j].data);
        }
    }
    delete objectNew2;

    printf("Objects using MALLOC===============================\n");
    //notice the double pointer being allocated double pointers the size of pointers to myObject
    myObject** objectMalloc =(myObject**) malloc(sizeof(myObject*)*r);

    for(int i=0;i<r;i++)
    {
        //now we are assigning array of pointers the size of myObject to each double pointer
        objectMalloc[i] = (myObject*) malloc(sizeof(myObject)*c);
        for(int j=0;j<c;j++){
            objectMalloc[i][j] = myObject(10*i+j);
            //notice that we access  data without dereferencing (.)
            printf("objectMalloc[%2d][%2d]=%02d\n",i,j,objectMalloc[i][j].data);
        }
    }
    free((void*) objectMalloc);

    //same as Malloc
    printf("Objects using CALLOC===============================\n");
    myObject** objectCalloc = (myObject**) calloc(r,sizeof(myObject*));

    for(int i=0;i<r;i++)
    {
        objectCalloc[i] = (myObject*) calloc(c,sizeof(myObject));
        for(int j=0;j<c;j++){
            objectCalloc[i][j] = myObject(10*i+j);
            printf("objectCalloc[%2d][%2d]=%02d\n",i,j,objectCalloc[i][j].data);
        }
    }
    free((void*) objectCalloc);

    printf("Int using NEW===============================\n");
    //int is not an object
    int** intNew = new int* [r];

    for(int i=0;i<r;i++)
    {
        intNew[i] = new int[c];
        for(int j=0;j<c;j++){
            intNew[i][j] = 10*i+j;
            printf("intNew[%2d][%2d]=%02d\n",i,j,intNew[i][j]);
        }
    }
    delete intNew;

    printf("Int using malloc===============================\n");
    int** intMalloc =(int**) malloc(sizeof(int*)*r);

    for(int i=0;i<r;i++)
    {
        intMalloc[i] =(int*) malloc(sizeof(int)*c);
        for(int j=0;j<c;j++){
            intMalloc[i][j] = 10*i+j;
            printf("intMalloc[%2d][%2d]=%02d\n",i,j,intMalloc[i][j]);
        }
    }
    free((void*) intMalloc);
    getchar();
    return 0;
}

Ответы [ 5 ]

7 голосов
/ 04 февраля 2011
  • new и new[] осведомлены о конструкторе, функции распределения памяти в C не доступны.
  • Аналогично, delete и delete [] распознают деструктор, тогда как free isn 't.
  • realloc не работает с памятью, выделенной с помощью new, не существует стандартов, определенных для функции realloc с функциями управления памятью в C ++.
  • Doне смешивать new и delete с malloc / calloc / realloc и free (т. е. не free никакой памяти, выделенной с new, не delete любой выделенной памятис malloc)

  • Если вы делаете new [], вам, скорее всего, следует использовать std::vector, который инкапсулирует все это управление памятью для вас.

  • Если вы используете выделенные в памяти необработанные указатели, вам лучше использовать интеллектуальные / полуумные указатели, такие как boost::shared_ptr или boost::scoped_ptr или std::auto_ptr, в зависимости от ваших потребностей.

  • Спасибо Дэвиду Торнли за то, что подняли этот вопрос:

  • Никогда не смешивайте скалярные new и delete сих массив формируется, то есть не delete[] память выделяется с new, и delete память не выделяется с new[].Неопределенное поведение вокруг.

  • В вашем примере вы ДОЛЖНЫ использовать new и new[], если должны, потому что, как я уже сказал, они осведомлены о конструкторе, а ваш класс нетип данных POD , поскольку он имеет конструктор.

Дополнительные сведения см. в разделе часто задаваемых вопросов по C ++:

3 голосов
/ 04 февраля 2011

1) Должен ли я использовать malloc в c ++ или новый? Если я использую new, могу ли я использовать realloc?

Используйте new. И никогда не используйте realloc с new.

Когда я должен использовать realloc? Что последствия использования его с точки зрения производительности и ошибок?

Вместо использования realloc я обычно реализую свой собственный пул памяти, из которого я перераспределяю память, когда мне это нужно. Это также улучшает производительность.

0 голосов
/ 04 февраля 2011

В общем, вам следует избегать распределения памяти в C ++.Большинство (не все) массивы можно сделать с std::vector лучше, чем вы собираетесь делать самостоятельно, особенно если вы здесь делаете ошибку.

Вы выделяете, скажем, intNew и intNew[i].Затем вы delete [] intNew; (скобки здесь необходимы, опускание их - ошибка), без delete [] ни одного из intNew[i].Выделенные одномерные массивы теперь являются утечками памяти и не могут быть освобождены, потому что вы потеряли все ссылки на них.Ни C, ни C ++ обычно не поставляются с сборщиком мусора.

Функции выделения памяти в C работают только с памятью.Они не являются типобезопасными и не вызывают конструкторы или деструкторы.Они могут использоваться с типами данных, которые не требуют ни того, ни другого, но вы должны убедиться, что они не делают ни того, ни другого.(Возможно malloc память и использование размещения new для создания там объектов, но это более продвинуто.)

Функции выделения памяти в C ++ работают с памятью и объектами.В основном они безопасны от типов и вызывают конструкторы и деструкторы.Не все объекты можно безопасно перемещать, поэтому нет эквивалента malloc.Сложность в том, что вы должны сопоставить new с delete и new[] с delete[].У вас есть эта ошибка в вашем коде: delete intNew; должно быть delete [] intNew;.

0 голосов
/ 04 февраля 2011

Если вы хотите писать программы на C ++ (!!), не используйте malloc, realloc, free.Это просто не функции C ++.

И нет необходимости использовать новые в ваших случаях (я говорю о примере).Вы должны использовать вектор или другой контейнер.

0 голосов
/ 04 февраля 2011

Должен ли я использовать malloc в c ++ или новый?Если я использую new, могу ли я использовать realloc?

Вы можете использовать malloc в C ++;однако, это настоятельно не рекомендуется в большинстве случаев.Кроме того, если вы звоните malloc, calloc, realloc и т. Д., Вам нужно использовать free для освобождения памяти после завершения.

Если вы используете new для выделения памятивы должны использовать delete, чтобы освободить его.

Процедуры выделения C не имеют безопасности типов.new делает.

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