Подтвердить что ты не робот

Что делать, если я удаляю массив один раз в С++, но распределяю его несколько раз?

Предположим, у меня есть следующий фрагмент.

int main()
{
    int num;
    int* cost;
    while(cin >> num)
    {
        int sum = 0;
        if (num == 0)
          break;

        // Dynamically allocate the array and set to all zeros
        cost = new int [num];
        memset(cost, 0, num);
        for (int i = 0; i < num; i++)
        {
            cin >> cost[i];
            sum += cost[i];
        }
        cout << sum/num;
    }
`  `delete[] cost;
    return 0;
}

Хотя я могу перемещать оператор delete внутри цикла while для моего кода, для понимания целей, я хочу знать, что происходит с кодом, как он писал. Разделяет ли С++ разные пространства памяти каждый раз, когда я использую оператор new?

Ли оператор delete удаляет только последний выделенный массив cost?

4b9b3361

Ответ 1

Разделяет ли С++ разные пространства памяти каждый раз, когда я использую оператор new?

Да.

Ли оператор delete удаляет только последний выделенный массив cost?

Да.

Вы потеряли единственные указатели на других, поэтому они безвозвратно просочились. Чтобы избежать этой проблемы, не жонглируйте указателями, но используйте RAII для автоматического управления динамическими ресурсами. std::vector был бы идеальным здесь (если бы вам вообще нужен массив, ваш пример мог бы просто продолжать чтение и повторное использование одного int).

Ответ 2

Я настоятельно рекомендую вам не использовать "C-идиомы" в программе на С++. Пусть библиотека std работает для вас: почему она там. Если вы хотите "массив (вектор) из n целых чисел", то это то, что std::vector, и оно "поставляется с включенными батареями". Вам не нужно обезопасить себя такими вещами, как "установка максимального размера" или "установка нуля". Вы просто работаете с "этой штукой", чья внутренняя работа, которую вы не должны... заботиться, зная, что она уже тщательно разработана и протестирована.

Кроме того, когда вы это делаете, вы работаете в существующей структуре С++ для управления памятью. В частности, вы не делаете ничего "вне диапазона" в своем собственном приложении ", о котором стандартная библиотека не знает, и которая может (!!) это сделать".

С++ дает вам очень обширную библиотеку быстрой, эффективной, надежной и проверенной функциональности. Используйте его.

Ответ 3

В вашем коде нет массива cost. В вашем коде cost есть указатель, а не массив.

Реальные массивы в вашем коде создаются повторяющимися вызовами new int [num]. Каждый вызов new создает новый, независимый, безымянный объект массива, который живет где-то в динамической памяти. Новый массив, созданный с помощью new[], доступен с помощью указателя cost. Поскольку массив является безымянным, указатель cost - это единственная ссылка, которая ведет к этому безымянному массиву, созданному new[]. У вас нет других средств для доступа к этому безымянному массиву.

И каждый раз, когда вы делаете это cost = new int [num] в своем цикле, вы создаете совершенно новый, другой массив, разбивая связь с cost на предыдущий массив и делая cost, чтобы указать на новый.

Так как cost была вашей единственной ссылкой на старый массив, этот старый массив становится недоступным. Доступ к этому старому массиву теряется навсегда. Это становится утечкой памяти.

Как вы правильно сформулировали это, ваше выражение delete[] освобождает только последний массив - в конце концов заканчивается один cost. Конечно, это верно, только если ваш код когда-либо выполняет строку cost = new int [num]. Обратите внимание, что ваш цикл может завершиться без отдельного выделения, и в этом случае вы примените delete[] к неинициализированному (мусорному) указателю.

Ответ 4

Да. Таким образом, вы получаете утечку памяти для каждой итерации цикла, за исключением последней.

Когда вы используете new, вы выделяете новый кусок памяти. Присвоение результата new указателю просто изменяет то, на что указывает этот указатель. Он автоматически не освобождает память, на которую ранее указывался указатель (если таковой был).

Ответ 5

Сначала эта строка неверна:

memset(cost, 0, num);

Предполагается, что int - это только один char long. Чаще всего это четыре. Вы должны использовать что-то вроде этого, если хотите использовать memset для инициализации массива:

memset(cost, 0, num*sizeof(*cost));

Или еще лучше сбрасывать memset и использовать это при распределении памяти:

cost = new int[num]();

Как указывали другие, удаление помещено неправильно и будет утечка всей памяти, выделенной соответствующим новым, за исключением последнего. Переместите его в цикл.

Ответ 6

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