Динамическое выделение памяти для объектов в C ++ - PullRequest
4 голосов
/ 25 июля 2011

Я пытаюсь динамически распределять (это не так динамично, как сейчас, но в конечном итоге будет) память для объектов в очень простой программе на C ++.Я новичок в классах и только недавно начал играть с C ++, оставив C позади.Вот код:

#include <iostream>
using namespace std;

class Test {
  private:
    int i;
  public:
    Test(int);
    ~Test();
    void print();
};

Test::Test(int ii) { i = ii; }
Test::~Test() { i=0; cout << "deconstructor called...value of i= " << i << endl; }
void Test::print() { cout << "value of i= " << i << endl; }

int main()
{
  Test a(10),*b,*c;
  //a.print(); // this works

  b = new Test(12);
  //b->print(); // this works as well

  for (int i=0; i<2; i++)
    c = new Test(i);

  c->print(); /* this shows that the value of i=1 .. should be 0? */
  c[0].print(); /* as expected (I guess), this prints i=1 as well... [expected because c->print() shows i=1 also */
  c[1].print(); /* shows value of i=0... */

  //delete []c; /* this fails miserably, but `delete c` works, why :( */

}

Большая часть моей путаницы фактически включена в комментарии в самом коде.Я в основном пытаюсь получить массив c , где каждый элемент массива является объектом сам по себе.

Поведение кода, который я получаю, описано в комментариях.

Ответы [ 6 ]

5 голосов
/ 25 июля 2011

Возможно, нам следует взглянуть на расширенные объявления:

Test a(10);
Test *b;
Test *c;

Вы определили b и c как указатель на Test, но, похоже, вы хотите, чтобы c был массивом указателей-тестировать.Заявление для c, которое вы намеревались, вероятно, было:

Test **c;

, которое вы бы инициализировали:

c = new Test*[2];

for (int i=0; i<2; i++)
   c[i] = new Test(i);

и к которому вы бы получили доступ таким образом:

c[0]->print();
c[1]->print();
5 голосов
/ 25 июля 2011

Есть несколько серьезных проблем с данным кодом.

  1. Выполняет new на *b, но пропустил delete it.
  2. Вы перезаписываете *c несколько раз в цикле for, что приведет к утечке объем памяти. Всегда освобождайте ресурсы перед выделением нового из указатель.
  3. Если вы выделяете new/new[]/malloc, вы должны освободить указатель с delete/delete[]/free соответственно. то же самое вы не поддерживаете с *c (вот почему он не работает).

Кроме того, помимо изучения динамического распределения, следует также знать о контейнерах STL, которые обеспечивают лучший способ обработки динамических ресурсов. например станд :: вектор .

0 голосов
/ 05 июня 2018

Смотри, по-моему, ты выделил память для * c несколько раз как

for (int i=0; i<2; i++)
c = new Test(i);

Посмотрите на этот код, который все прояснит

for (int i=0; i<2; i++)
{   c = new Test(i);    }       /*see , here the loop goes for i=0; then
                                for i=1; which basically overwrites what c will have
                                 i.e. finally       c = new test(1); */
c->print(); /* works fine , gives value of i=1 */
c[0].print(); /* as expected , this prints i=1 as well... */
c[1].print(); /*clearly, it will give a garbage value */
delete c;

Но, по-моему, было бы лучше заменить

for (int i=0; i<2; i++)
{   c = new Test(i);    }

с

c = new Test(1);    //as the previous code is doing the same in for loop but that was consuming more resources

Так что, если вы хотите выводить как i = 0, а затем i = 1, то сделайте так -

c = new int(0);
c->print(); /* works fine , gives value of i=0 */
c[0].print(); /* as expected , this prints i=0 as well... */
delete c;

c = new int(1);
c->print(); /* works fine , gives value of i=1 */
c[0].print(); /* as expected , this prints i=1 as well... */
delete c;

Приведенный выше код - это то, что полностью удовлетворит ваши потребности.

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

delete c[]; Удаляет только начальный элемент.Если вы хотите удалить этот массив, используйте dz delete c[] в для цикла

Вам не удалось выделить память для c и продолжать неправильно кодировать ее, как вы можете получить выходные данные без выделения памяти для переменной-указателя?

0 голосов
/ 25 июля 2011

То, что delete[] не работает, совершенно нормально: вы никогда не выделяли c как массив, а как указатель. Вы можете хранить адрес массива в указателе, но это все. Мне действительно интересно, почему именно c [1] работает, потому что ваш цикл for просто хранит многократно указатели на вновь размещенные объекты в одном и том же указателе (вы не заполняете массив!).

0 голосов
/ 25 июля 2011
for (int i=0; i<2; i++)
    c = new Test(i);

Приведенный выше код утечки памяти.c просто указывает на последний построенный объект в итерации цикла.

c-> print ();/ * это показывает, что значение i = 1 .. должно быть 0?

Здесь c указывает на местоположение, построенное на new Test(1);.Итак, выходные данные.

Каждый новый [] должен сопровождаться delete [] и new с delete ,Вы не можете смешивать оба.

...