Операторы new и delete

С указателями на объекты нельзя использовать механизм выделения malloc() и освобождения free() динамической памяти языка Си, так как выделение памяти под объект не вызывает его констуктор, в результате возникает неинициализированный объект, который ведёт себя непредсказуемо.

class tStudent{
    int age;
public:
    tStudent(int _age) {
        age = _age;
    }
    ~tStudent() {
        cout << "Dismissed..." << endl;
    }
    void aging() {
        age++;
        cout << "Happy birthday! New age: " << age << endl;
    }
};

int main() {
    tStudent *p1 = ( tStudent *)malloc(sizeof(tStudent)); //Не был вызван констуктор!!!
    p1->aging(); //Ошибка! В возрасте студента — мусорное значение.
    free(p1);
}

Чтобы не нарушать логики С++ нужен новый механизм работы с динамической памятью — операторы new и delete.

Иcпользование данных операторов с объектами и только их должно быть правилом!

tStudent *p2 = new tStudent(17); //Выделена память и вызван констуктор
    //с параметром, который инициализирует приватный age.
p2->aging(); //Всё в порядке
delete p2; //освобождается память, но перед этим вызывается
    //деструктор соответствующего экземпляра.

Изменение приватных полей по-прежнему запрещено. Компилятор следит за этим, и выведет ошибку увидев, например, p2->age = 17;

Отлично! Задача решена.

new

Операция new предназначена для создания объекта.

int *p = new int; //выделить память для одного int
int *pp = new int [10]; //выделить память для массива размера 10.

Время жизни объекта, созданного с помощью new, не ограничивается областью видимости, в которой он был создан. Операция new возвращает указатель на созданный объект. Если объект является массивом, возвращается указатель на начальный элемент массива. Например, обе операции new int и new int[1] возвратят int* , а типом new int[i][10] будет int(*)[10]. Если описывается тип массива, все размерности, кроме первой, должны быть выражениями-константами с положительным значением. Первая размерность массива может задаваться произвольным выражением.

delete

Операция delete уничтожает объект, созданный с помощью new.

delete p; //для удаления одного объекта
delete[] pp; //для удаления динамического массива

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

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

Результат удаления массива с помощью простого обращения delete не определен, так же как и удаление одиночного объекта с помощью delete [].

Операция delete вызывает деструктор (если он есть) для объекта, на который настроен ее операнд.

Нельзя удалять указатель на константу!

Нельзя мешать!

Для классических, не классовых типов в проекте может быть использован и старый механизм выделения и освобождения памяти malloc()/free(), но его никогда нельзя смешивать с new/delete.

Память выделена и освобождена в новом стиле

int *p = new int;
delete p;

ОК. Память выделена и освобождена в старом стиле

int *p = (int *)malloc(sizeof(int));
free(p);

Память выделена в старом стиле, а освобождена в новом. Ошибка!

int *p = (int *)malloc(sizeof(int));
delete p;

Память выделена в новом стиле, а освобождена в старом. Ошибка!

p = new int;
free(p);