← Назад к вопросам

Чем отличается 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 гарантирует правильное освобождение памяти
Чем отличается delete от delete[]? Что будет, если перепутать? | PrepBro