Динамическое распределение памяти объектов в C ++
-
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();
Другие советы
Есть несколько серьезных проблем с данным кодом.
- Исполнение
new
на*b
но пропустилdelete
Это. - Вы перезаписываете
*c
Несколько раз вfor
петля, которая протекает память. Всегда разбирайте ресурсы, прежде чем выделить новый из указателя. - Если вы распределяете с
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;
Приведенный выше код - это то, что полностью удовлетворит вашу потребность.