для циклов в C ++ с массивами и указателями - PullRequest
0 голосов
/ 03 ноября 2018

Мой учитель познакомил нас с циклическим просмотром массива в следующем формате:

int size;
cin >> size;
int *garbage = new int[size];
for (int* p = garbage; p < (garbage + size); p++) {
    if (*p > *max) {
        max = p;
    }
}

Я понимаю, что происходит, но это просто странно для меня как новая концепция. Есть ли лучшие способы пройти через такой массив?

Второй вопрос: нужно ли указывать каждый указатель на nullptr, как только вы закончите с ним? Например, вызывает ли утечка памяти такой цикл for, как у указателя p, или он самоуничтожается после выхода из области цикла for?

Ответы [ 4 ]

0 голосов
/ 04 ноября 2018

в C ++ 11 вы можете сделать это:

int max = 0;
std::vector<int> mem;
for (auto &i : mem)
    if (i > max)
        max = i;
0 голосов
/ 03 ноября 2018

Конечно, есть лучшие (как в - более читабельные) способы перебора массива. Например:

for (int index = 0; index < size; index++) {
    if (p[index] > *max) {
        max = &p[index];
    }
}

Однако, как вы видите в присваивании max = ..., проще иметь указатель на элемент массива, если вы хотите передать его другой переменной-указателю.

Относительно вашего второго вопроса - нет никакой внутренней ценности в установке его на nullptr. Однако, чтобы предотвратить утечки памяти, вы должны освободить (освободить) память, зарезервированную с помощью оператора new, используя оператор delete, как только вы закончите работу с массивом, например:

delete [] p;

РЕДАКТИРОВАТЬ: Обратите внимание, что вы не сможете безопасно разыменовать указатель max (то есть вы не можете прочитать, что int он указывает на выражение *max) после освобождения массива, не вызывая Undefined Поведение и, возможно, сбой вашей программы, потому что ваша программа вернет зарезервированную память ОС и не будет иметь к ней доступа.

Спасибо @ user4581301 за указание на это.

0 голосов
/ 03 ноября 2018

Есть еще один способ решения проблемы. Существует алгоритм стандартной библиотеки C ++ для поиска максимального элемента в диапазоне: std::max_element. Рукописный цикл не требуется.

int max = *std::max_element(garbage, garbage + size);

Обратите внимание, что он возвращает итератор (в данном случае указатель), поэтому я использовал *, чтобы получить значение от итератора.

Вашему учителю может не понравиться это решение.

0 голосов
/ 03 ноября 2018

Это немного чище:

int size = 10, max = 0;
int *mem = new int[size];
int *end = mem + size;
for (int *p = mem; p < end; p++)
    if (*p > max)
        max = *p;

Но если вы начнете использовать C ++ 11, вы можете сделать это:

int max = 0;
std::vector<int> mem;
for (auto &i : mem)
    if (i > max)
        max = i;

Возможно, есть даже более простые способы использования других инструментов пространства имен std.

вам нужно повернуть каждый указатель на nullptr, как только вы закончите с ним?

Нет, но это очень помогает при отладке. Если вы используете освобожденный указатель, для которого не установлено значение nullptr, вы будете намного более сбиты с толку, чем если бы это был nullptr. Установка указателя на nullptr фактически не освобождает память автоматически. Вам все еще нужно вызвать соответствующую «свободную» функцию, прежде чем устанавливать в nullptr.

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