порядок вычисления нового выражения в C 17

#c #c 17 #language-lawyer

#c #c 17 #язык-юрист

Вопрос:

По правилу cppreference/eval_order 12 вызов функции распределения ( operator new ) выполняется последовательно перед (начиная с C 17) вычислением аргументов конструктора в новом выражении. Таким образом, я подумал следующее

 Bar b;
Foo* f = new Foo(b.fun());
 

во время выполнения new сначала вызывается, затем fun() on b и, наконец, конструктор Foo . И Clang, и ICC создают этот порядок. Однако fun() сначала вызывается GCC, затем operator new конструктор, а затем конструктор.

Кто прав? Чего мне не хватает?

Комментарии:

1. Это gcc.gnu.org/bugzilla/show_bug.cgi?id=86347

2. Учитывая, что новое выражение может создавать Foo объект на месте в памяти, выделенной new , это выглядит неоптимальным… Как вы его тестировали, загружали new и печатали?

3. @StoryTeller-UnslanderMonica, да, тем временем я тоже нашел. Это сообщение об ошибке более чем 2-летней давности, поэтому его устранение все еще в пути… Даже если это может быть не так важно, но более 2 лет, давайте, ребята! В любом случае, спасибо!

4. @Yakk-AdamNevraumont, да, перегрузить новое.

Ответ №1:

Изучение стандарта (версия N4835.pdf):

7.6.2.7 Новый [expr.new]
23 Вызов функции распределения выполняется последовательно перед вычислениями выражений в новом инициализаторе. Инициализация выделенного объекта выполняется последовательно перед вычислением значения нового выражения.

В вашем случае b.fun() это единственное выражение в новом инициализаторе.

Похоже, что Clang, ICC и MSVC делают это правильно, а GCC делает это неправильно. Возможно, стоит спросить ребят из GCC и, возможно, отправить отчет об ошибке (или, может быть, он уже существует?).

Комментарии:

1. Это не обязательно, но было бы неплохо добавить ссылку на черновик, на который вы ссылаетесь.