Динамическое распределение памяти объектов в C ++

StackOverflow https://stackoverflow.com/questions/6811508

  •  25-10-2019
  •  | 
  •  

Вопрос

Я пытаюсь динамически распределить (это не так динамично, как сейчас, но в конечном итоге это будет) память для объектов в очень Простая программа 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 :( */

}

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

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

Это было полезно?

Решение

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

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

Вы определили B и C как указатель к тесту, но вы, кажется, хотите, чтобы 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();

Другие советы

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

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

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

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

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

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

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

Каждый новый[ должно сопровождаться Удалить[ а также новый с Удалить. Анкет Вы не можете смешать оба.

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

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

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

Смотрите по моему мнению, вы выделили память за *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;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top