- 1
while(new char != NULL) {}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
0
while(new char != NULL) {}
В Делфи большинство объектов имеют фабрику (конструкторы там всякие, деструкторы), а здесь объект инициализируется именно вызовом new.
Вот, что штампуют в википездии:
new — оператор языка программирования C++, обеспечивающий выделение динамической памяти в куче. За исключением формы, называемой «размещающей формой new», new пытается выделить достаточно памяти в куче для размещения новых данных и, в случае успеха, возвращает адрес выделенного участка памяти. Однако, если new не может выделить память в куче, то он передаст (throw) исключение типа std::bad_alloc. Это устраняет необходимость явной проверки результата выделения. После встречи компилятором ключевого слова new им генерируется вызов конструктора класса[1].
> Однако, если new не может выделить память в куче, то он передаст (throw) исключение типа std::bad_alloc.
А вот это уже ценное замечание. Если в случае неудачи аллокатор бросает исключение и никогда не возвращает NULL, то данный код компилятор может оптимизировать до такого:
Всё равно выход из цикла только по исключению.
Тем не менее, «неоптимизированная» форма ошибкой не является. Ошибкой является то, что мы никуда не сохраняем полученный указатель.
new может быть определён пользователем и следует другому контракту: либо кидает исключение, либо выдаёт новый кусочек памяти. Оптимизации всё равно должны учитывать оба варианта этого поведения.
http://stackoverflow.com/questions/31873616/is-the-compiler-allowed-to-optimize-out-heap-memory-allocations
> This is allowed by N3664. This proposal is part of the C++14 standard, so in C++14 the compiler is allowed to optimize out a new expression (even if it might throw).
An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1, 18.6.1.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the lifetime of the object allocated by e1 strictly contains the lifetime of the object allocated by e2, e1 and e2 would invoke the same replaceable global allocation function, and, for a throwing allocation function, exceptions in e1 and e2 would be first caught in the same handler.
Выкинутый new обязательно должен быть склеен с другим new (то есть хотя бы один new должен остаться), либо результат должен быть "provided by the implementation", а никакая реализация не сможет бесконечно выделять новую память, и в конце концов кинет исключение.
Т.е. в общем-то и на стеке может запилить, если увидит пару из new и delete, а указатель наружу не утекает.
Вот шланг выпиливает new из кода выше https://godbolt.org/g/QrWwRk
https://godbolt.org/g/FveCUw
Видимо, тут он пользуется какими-то своими знаниями о дефолтном операторе new, а не о конструкции выделения памяти.