Ответ 1
Да, это законно. expr.new/10
для С++ 14:
Реализация разрешается опускать вызов сменной глобальной (18.6.1.1, 18.6.1.2). Когда это происходит, хранилище вместо этого обеспечивается реализацией или обеспечивается путем расширения выделение другого нового выражения.
expr.delete/7
:
Если значение операнда выражения-удаления не является нулевым значение указателя, затем:
- Если вызов выделения для нового выражения для объекта исключение не было опущено и распределение не было расширено (5.3.4), выражение-выражение должно вызывать функцию освобождения (3.7.4.2). Значение, возвращаемое из вызова выделения нового выражения должен быть передан в качестве первого аргумента функции освобождения.
- В противном случае, если распределение было расширено или было предоставлено расширяя выделение другого нового выражения, и delete-expression для любого другого значения указателя, созданного новое выражение, у которого было хранилище, предоставленное расширенным новое выражение было оценено, выражение-выражение должно вызвать функция освобождения. Значение, возвращаемое из вызова распределения расширенное новое выражение должно быть передано в качестве первого аргумента в функция освобождения.
- В противном случае выражение delete не будет вызывать освобождение функция (3.7.4.2).
Итак, в заключение, законно заменить new
и delete
на какую-то реализацию, определенную, например, используя стек вместо кучи.
Примечание. Как комментирует Массимилиано Джанс, компилятор не мог точно придерживаться этого преобразования для вашего образца, если do_something
throws: компилятор должен опустить деструкторный вызов f
в этом случае (в то время как ваш преобразованный образец вызывает деструктор в этом случае). Но кроме этого, можно положить f
в стек.