← Назад к вопросам
Чем отличается delete от delete[]? Что будет, если перепутать?
1.2 Junior🔥 181 комментариев
#Структуры данных и алгоритмы#Умные указатели и управление памятью#Язык C++
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Delete vs Delete[]: Критическая Разница
delete и delete[] — это два разных оператора в C++ для освобождения динамической памяти, и их путаница приводит к undefined behavior, утечкам памяти и краху приложения.
Основные Различия
| Оператор | Предназначение | Используется для | Правило |
|---|---|---|---|
| delete | Освобождение одного объекта | new Type | Один new → один delete |
| delete[] | Освобождение массива объектов | new Type[] | Один new[] → один delete[] |
Почему Это Важно
Когда создаёте объект с new, компилятор может сохранить информацию о размере массива в специальном месте. При освобождении:
- delete — удаляет один объект, вызывает деструктор один раз
- delete[] — удаляет массив, вызывает деструкторы для каждого элемента
Пример 1: Правильное Использование
#include <iostream>
class Object {
public:
Object() { std::cout << "Конструктор" << std::endl; }
~Object() { std::cout << "Деструктор" << std::endl; }
};
int main() {
Object* single = new Object;
delete single;
Object* arr = new Object[5];
delete[] arr;
return 0;
}
Пример 2: Опасность - delete вместо delete[]
#include <iostream>
class Resource {
public:
int value;
Resource(int v) : value(v) {
std::cout << "Создан объект" << std::endl;
}
~Resource() {
std::cout << "Удалён объект" << std::endl;
}
};
int main() {
Resource* arr = new Resource[3];
delete arr; // НЕПРАВИЛЬНО!
return 0;
}
Результат: undefined behavior
- Деструктор вызовется только для первого элемента
- Утечка памяти
- Возможен крах приложения
Пример 3: Опасность - delete[] вместо delete
int main() {
int* single = new int(42);
delete[] single; // НЕПРАВИЛЬНО!
return 0;
}
Результат: undefined behavior
- Попытается прочитать размер массива
- Коррумпция heap
- Крах приложения
Пример 4: Реальная Проблема с Деструкторами
#include <iostream>
class Person {
private:
char* name;
public:
Person(const std::string& n) {
name = new char[n.length() + 1];
strcpy(name, n.c_str());
}
~Person() {
delete[] name;
}
};
int main() {
Person* people = new Person[3];
delete[] people; // Правильно: вызовет деструктор каждого
return 0;
}
Последствия Путаницы
1. Утечки Памяти
class Data {
int* buffer;
public:
Data() : buffer(new int[1000]) {}
~Data() { delete[] buffer; }
};
void leakExample() {
Data* arr = new Data[10];
delete arr; // ОШИБКА: только 1 объект удалён!
// 9 объектов остаются в памяти
}
2. Крах Приложения
int main() {
std::vector<int>* v = new std::vector<int>[5];
delete v; // ОШИБКА: segmentation fault
return 0;
}
Лучшие Практики
1. Используй Smart Pointers (Рекомендуется)
#include <memory>
int main() {
std::unique_ptr<int> single(new int(42));
std::unique_ptr<int[]> arr(new int[100]);
auto arr2 = std::make_unique<int[]>(100);
return 0; // Память автоматически освобождается
}
2. Правило RAII
class MyArray {
private:
int* data;
size_t size;
public:
MyArray(size_t sz) : size(sz) {
data = new int[size];
}
~MyArray() {
delete[] data; // Правильный оператор
}
MyArray(const MyArray&) = delete;
};
3. Мнемоника для Запоминания
int* p1 = new int; // new (единственное число)
delete p1; // delete (единственное число)
int* p2 = new int[10]; // new[] (множественное число)
delete[] p2; // delete[] (множественное число)
Сравнение Подходов
// 1. Raw pointers (опасно)
int* arr = new int[100];
delete[] arr;
// 2. std::unique_ptr (безопаснее)
auto arr = std::make_unique<int[]>(100);
// 3. std::vector (рекомендуется для массивов)
std::vector<int> arr(100);
// 4. std::array (для статического размера)
std::array<int, 100> arr;
Ключевые Выводы
- new соответствует delete, new[] соответствует delete[]
- Путаница приводит к undefined behavior
- Используй smart pointers вместо raw pointers
- RAII гарантирует правильное освобождение памяти