Справочное руководство по C++
Шрифт:
Время жизни объекта, созданного с помощью new, не ограничивается областью видимости, в которой он был создан. Операция new возвращает указатель на созданный объект. Если объект является массивом, возвращается указатель на начальный элемент массива. Например, обе операции new int и new int[1] возвратят int*, а типом new int[i][10] будет int(*)[10]. Если описывается тип массива (§R.8.2.4), все размерности, кроме первой, должны быть выражениями-константами (§R.5.19) с положительным значением. Первая размерность массива может задаваться произвольным выражением, даже если используется имя-типа (здесь нарушается общее требование, чтобы размерности массива в конструкции имя-типа были выражениями-константами (§R.5.19)).
Допускается, чтобы вызывалась функция operator new с параметром нуль. В таком случае возвращается указатель на объект. При повторении таких вызовов будут возвращаться указатели на разные объекты.
Конструкция список-спецификаций-типа не должна содержать const, volatile, описание класса или перечисления.
Для резервирования памяти операция new обращается к функции operator new (§R.12.5). При размещении объекта типа T ей в качестве первого параметра передается sizeof(T). Конструкция параметры-new используется для передачи дополнительных параметров. Например, операция new T приводит к вызову operator new(sizeof(T)), а операция new(2,f) T приводит к вызову operator new(sizeof(T),2,f).
Конструкция параметры-new может использоваться только, если описана функция operator new с параметрами соответствующих типов.
Если с помощью операции new создается объект не типа класс (в том числе и массив объектов типа класс), то вызывается глобальная функция ::operator new. Если с помощью new создается объект класса T, вызывается функция T::operator new, если она существует (используя обычные правила просмотра при поиске членов класса и его базовых классов, §R.10.1.1), иначе вызывается глобальная функция ::operator new. Использование операции ::new гарантирует, что будет вызываться глобальная функция ::operator new, даже если существует T::operator new.
Конструкция выражение-размещения может содержать инициализатор-new. Для объектов классов с конструкторами (§R.12.1) задаваемый ею список параметров будет использоваться при вызове конструктора, в других случаях конструкция инициализатор-new должна иметь вид (выражение) или . Если выражение присутствует, оно используется для инициализации объекта, если его нет, объект начнет существование с неопределенным значением.
Если класс имеет конструктор, объект этого класса можно создать с помощью new только при условии, что заданы подходящие параметры, или, что класс имеет стандартный конструктор (§R.12.1). Отводит ли память при создании объекта типа класс сама функция operator new, или оставляет это на конструктор,
Для массивов нельзя задавать инициализаторы. Массивы объектов типа класса с конструктором можно создавать с помощью операции new только, если конструктор класса является стандартным (§R.12.1). В этом случае стандартный конструктор будет вызываться для каждого элемента массива.
Инициализация производится только в том случае, когда функция operator new возвращает ненуль. Если она возвращает 0 (пустой указатель), значение выражения есть 0.
Порядок вычисления выражения вызова operator new для получения памяти и порядок вычисления параметров конструктора неопределен. Так же неопределено вычисляются ли параметры конструктора, если функция operator new возвратила 0.
В конструкции имя-типа-new скобки использовать необязательно. Тогда обращение
может привести к ошибке, т.к. операции применяются в таком порядке
Объекты сложного типа можно задать в операции new с помощью явно указанных скобок, например, обращение
размещает массив из 10 указателей на функции (не имеющие параметров и возвращающие int).
Конструкции имя-типа-new в выражение-размещения должна быть самой длинной из возможных последовательностей конструкций описатель-new. Это предотвращает коллизии между операциями из описателей &, *, [] и их двойниками из выражения, например,
Символ * используется в описателе указателя, а не в качестве операции умножения.
R.5.3.4 Операция delete
Операция delete уничтожает объект, созданный с помощью new.
Результат имеет тип void. Операндом delete должен быть указатель, который возвращает new. Эффект применения операции delete к указателю, который не получен в результате операции new без задания параметры-new, считается неопределенным и обычно приводит к опасным последствиям. Однако гарантируется, что удаление по указателю с нулевым значением безопасно.
Результат попытки доступа к удаленному объекту неопределен, а удаление объекта может изменить его значение. Более того, если выражение, задающее объект, является изменяемым адресом, его значение после удаления неопределено.
Нельзя удалять указатель на константу.
Операция delete вызывает деструктор (если он есть $$12.4) для объекта, на который настроен ее операнд.
Для освобождения памяти, отведенной под указываемый объект, операция delete вызывает функцию operator delete (§R.12.5). Для объектов, не имеющих тип класс (в том числе и для массивов классов), используется глобальная функция ::operator delete. Для объекта типа класс T вызывается функция T::operator delete, если она есть (используя обычные правила просмотра при поиске членов класса и производных от него классов, §R.10.1.1), в противном случае вызывается глобальная функция::operator delete. Обращение ::delete гарантирует, что будет вызываться глобальная функция ::operator delete, даже если существует T::operator delete. Для удаления массивов используется обращение вида