Привет, мой друг-программист! 👋
Сегодня мы разберем тему, с которой начинается 90% багов, седых волос и ночных дебаггинг-сессий. Тема, которая кажется простой, но убивает джунов на собеседованиях за 2 секунды.
Я говорю о МАССИВАХ в C++.
Ты думаешь: «Что там сложного? int arr[5]; arr[0] = 10; — всё?»
О нет, дружочек. Сядь поудобнее. Сейчас я расскажу, почему 99% программистов используют массивы неправильно, и как делать это как настоящий сеньор.
💀 Факт: больше половины уязвимостей в старом коде — из-за неправильной работы с массивами. Сегодня мы сделаем так, чтобы твой код был бронебойным.
📦 Что такое массив? Максимально просто
Массив — это коробка с пронумерованными ячейками, где все ячейки одного типа.
Представь почтовые ящики в подъезде. У каждого номер (индекс), в каждом лежит что-то (значение). И все ящики одинакового размера.
Визуально в памяти это выглядит так:
🔑 Ключевой момент: массивы хранятся в памяти подряд (непрерывно). Именно поэтому к ним можно быстро обращаться — компьютер просто берет стартовый адрес + индекс * размер типа.
🎯 Три способа создать массив (выбери своего воина)
1️⃣ Классика — на стеке (самый частый)
✅ Плюсы: очень быстрый
❌ Минусы: размер фиксирован на этапе компиляции, память выделяется на стеке (максимум ~1-8 МБ)
2️⃣ Динамический — на куче (когда размер неизвестен заранее)
✅ Плюсы: размер можно задать во время выполнения
❌ Минусы: нужно вручную удалять, можно получить утечку
🧠 Запомни раз и навсегда:
new → delete
new[] → delete[]
Смешивать нельзя — это как заливать бензин в дизель.
3️⃣ std::array — современный (ЛУЧШИЙ)
✅ Плюсы: знает свой размер, безопасный, быстрый
❌ Минусы: размер все еще фиксирован на этапе компиляции
👑 Вывод: используй std::array, если знаешь размер заранее. Используй std::vector (о нем в конце), если размер меняется.
⚠️ ГЛАВНЫЕ ГРАБЛИ с массивами (читай как заклинание)
Грабли №1: Индексация с нуля
Самая частая ошибка новичков:
При этом компилятор НЕ ВЫДАСТ ОШИБКУ. Программа просто испортит память рядом с массивом (undefined behavior). И всё упадет через час в другом месте.
🔧 Лечение: всегда помни, что последний элемент — [size - 1].
Грабли №2: Массивы "умирают" при передаче в функцию
Это вообще убийца джунов. Смотри:
Почему так происходит?
Когда ты передаешь массив в функцию, он "превращается" (деградирует) в указатель на первый элемент. Функция не знает, сколько элементов было изначально.
🔧 Как лечить:
Способ 1: передавать размер отдельно
Способ 2: использовать std::array (он не теряет размер)
Грабли №3: Выход за границы (Никогда не делай так)
Это может:
- Сразу уронить программу
- Испортить другие переменные
- Создать уязвимость для хакеров
- Работать как ни в чем не бывало... до релиза в пятницу вечером
📌 Золотое правило: ВСЕГДА проверяй индекс, если есть хоть один шанс, что он может быть неверным.
🔥 Реальные примеры работы с массивами (код, который пригодится)
Пример 1: Ввод и вывод массива (как на собеседовании)
Пример 2: Поиск максимального элемента (100% будет на любом тестовом)
Пример 3: Пузырьковая сортировка (страшный сон джуна)
⏱️ Сложность: O(n²). Для больших массивов не используй, но для учебы — самое то.
Пример 4: Многомерные массивы (таблица умножения на стероидах)
Вывод:
В памяти 3D-массивы хранятся построчно (строка за строкой). Это важно для оптимизации.
🧠 Типичные задания с собеседований (от джуна до мидла)
Задание 1: Перевернуть массив (reverse)
Задание 2: Удалить дубликаты из отсортированного массива
Задание 3: Сдвинуть массив вправо на k позиций
💣 Динамические массивы: вся правда о new и delete
Самая частая ошибка студентов:
Правильно:
Почему это важно?
new int[100] выделяет память для 100 элементов плюс служебную информацию (обычно в начале). delete освободит только первый элемент, остальные 99 — утечка. delete[] знает про служебную информацию и корректно удаляет всё.
🛡️ std::array — спасение для джунов
🚀 Бонус: std::vector — когда размер меняется на лету
Простые массивы (обычные или std::array) имеют фиксированный размер. А если нужно добавлять элементы динамически?
Вот тут на сцену выходит std::vector (про него я расскажу подробнее в следующей статье).
💡 Совет профессионала: если не знаешь размер заранее — используй vector. Он медленнее обычного массива на наносекунды, но безопаснее и удобнее в разы.
📊 Когда какой массив использовать? Шпаргалка
🔥 Полный рабочий пример: Анализ оценок студентов
📢 Призыв к действию (да-да, снова)
Мы разобрали массивы от А до Я. Теперь ты знаешь больше 90% программистов, которые просто "копипастят с SO".
🔥 Твое задание на сегодня:
- Открой свой старый проект с массивами и перепиши его, используя std::array или std::vector
- Напиши функцию, которая находит второе максимальное число в массиве (без сортировки!)
- Подпишись на блог — в следующей части мы затроллим std::vector и узнаем, почему он лучше массивов везде и всегда
- Напиши в комментариях: «МАССИВЫ НЕ КУСАЮТСЯ», если статья была полезна
🎯 Итог (коротко и по делу)
💀 Финальный босс: что выведет этот код?
Ответ:
3
4
2
Да, да, 1[arr] работает в C++! Потому что arr[1] превращается в *(arr + 1), а сложение коммутативно → *(1 + arr) → 1[arr].
Никогда так не пиши в реальном коде, но на собеседовании можешь блеснуть 😎
Если хочешь вторую часть — про многомерные массивы, указатели на массивы и массивы указателей — поставь 💀 в комментах.
Пиши в комментариях свой любимый способ завалить массив (выход за границы, забытый delete, путаница с размерами).
Пока, и пусть твои индексы никогда не выходят за границы! 🤘
✍️ Твой сумасшедший C++ энтузиаст
#массивы #c++ #cpp #программирование #собеседование #блогпрограммиста