Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>- Скажите, пожалуйста, а вот такое в C++ по стандарту?
А>
А>void f ()
А>{
А> return void ();
А>}
А>
Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение.
А>А вот такое?
А>
А>void f () {}
А>void g ()
А>{
А> return g ();
А>}
А>
Здесь тоже самое несоответствие стандарту, так как после return стоит выражение.
А>Если да, то с какого момента?
А>И как вообще читать запись void ()?
А>Вызов конструктора void? Так ведь у встроенных типов нет конструкторов.
Это читается как тип функции, возвращающей void и не имеющей параметров.
А>- Допустим, у нас имеется такой код:
А>
А>String *newString = new String ("str");
А>
А>Если оператор new отработал некорректно, то вызов
А>
А>delete newString;
А>
А>вызовет UB, ведь так?
Если оператор new отработал некорректно, то оон сгенерирует исключение. Поэтому действительно вызов затем delete newString; является неопредленным поведением, если до этого вы не присвоили этому указателю нулевое константное значение.
Ежели вы установили, что new не будет генерировать исключение, а будет возвращаьб нулевое значение, как это принято в С в случае неуспеха, то в этом случае вызов delete будет корректным, так как вы вызовите этот оператор для нуллевого туказателя.
Здравствуйте, Сыроежка, Вы писали:
С>Здравствуйте, Аноним, Вы писали:
А>>Приветствую.
А>>- Скажите, пожалуйста, а вот такое в C++ по стандарту?
А>>
А>>void f ()
А>>{
А>> return void ();
А>>}
А>>
С>Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение. Кроме того это вообще должно выдать ошибку компиляции, так как вы не указали объект, а лишь пытаетесь вернуть тип объекта.
С>Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение.
Странно, потому что как Visual Studio, так и gcc абсолютно корретно отрабатывают данный код.
Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>- Скажите, пожалуйста, а вот такое в C++ по стандарту?
Да
5.2.3/2
The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object
type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized
(8.5; no initialization is done for the void() case).
и 6.6.3/3
A return statement with an expression of type “cv void” can be used only in functions with a return type
of cv void; the expression is evaluated just before the function returns to its caller.
А>Если да, то с какого момента?
По крайней, мере, начиная со стандарта 1998 года, т.е. это всегда так (по-стандарту) было.
А>И как вообще читать запись void ()?
А>Вызов конструктора void? Так ведь у встроенных типов нет конструкторов.
Это не вызов конструктора, а value-initialization (default-initialization в стандартах 1998 и 2003 г), для встроенных типов это инициализация 0-ми. Для void, как видно из цитаты никакой инициализации не происходит, просто получаем prvalue/rvalue.
Здравствуйте, Сыроежка, Вы писали:
С>Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение.
С>Здесь тоже самое несоответствие стандарту, так как после return стоит выражение.
Глупости. Всё законно:
6.3.3 3
A return statement with an expression of type “cv void” can be used only in functions with a return type
of cv void; the expression is evaluated just before the function returns to its caller.
Здравствуйте, YourLastSong, Вы писали:
С>>Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение.
YLS>Странно, потому что как Visual Studio, так и gcc абсолютно корретно отрабатывают данный код.
YLS>Ни Visual Studio, ни gcc ничего не сказали.
Я не совсем точно выразился. Еа самом деле выражение типа void может присутствовать в предложение return для функуции, возвращающей void. Не может присутствовать выражение, не имеющее тип void
В приведеннном примере имеет место
return void ();
Что такое void ()? На мой взгляд как выражение оно некорреткно. Что здесь первичное выражение? мы имеем пустые круглые скобки. Это напоминает задание типа функции. Но это же не имеет отношение к выражению. Поэтому мне представляется, что должна быть ощшибка компиляции. Или же здесь имеет место такая синтаксическая конструкция, которую я не вижу.
Здравствуйте, watch-maker, Вы писали:
WM>Здравствуйте, Сыроежка, Вы писали:
С>>Это не соответствует сттандарту, так как функция, имеющая тип возвращаемого значения void не должна содержать предложение return, содержащее выражение.
С>>Здесь тоже самое несоответствие стандарту, так как после return стоит выражение.
WM>Глупости. Всё законно:
WM>
WM>6.3.3 3
WM>A return statement with an expression of type “cv void” can be used only in functions with a return type
WM>of cv void; the expression is evaluated just before the function returns to its caller.
Я уже выше поправился. Проблема в том, что я не вижу в возвращаепмом значении примера выражение типа void.
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Аноним, Вы писали:
А>>Приветствую.
А>>- Скажите, пожалуйста, а вот такое в C++ по стандарту?
KO>Да
KO>5.2.3/2
KO>
KO>The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object
KO>type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized
KO>(8.5; no initialization is done for the void() case).
Я как-то раньше на это не разбирался в этих деталях, так как не было необходимости. Тепероь буду знать, что void() — это корректная конструкция.
Я так думаю, что это сделали из-за шаблонов, так как заранее неизвестно, какой тип будет использован в качестве аргумента, а потому чтобы не возникало ошибки компиляции при инстанировании шаблона, когда используется void разрешили такую конструкцию.
А>>String *newString = new String ("str");
А>>delete newString;
А>>
С>Если оператор new отработал некорректно, то он сгенерирует исключение. Поэтому действительно вызов затем delete newString; является неопределенным поведением, если до этого вы не присвоили этому указателю нулевое константное значение.
Если оператор new в этом коде выбросит исключение, до выполнения delete newString дело даже не дойдет. Так что неопределенного поведения не будет.
Здравствуйте, llex, Вы писали:
L>Точно сказать, что это не могу, но для встроенных типов запись вида L>"TYPE()" должна приравнивается к "(TYPE)", т.е. приведение типа.
с чего вдруг?
5.2.3/2
The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object
type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized
(8.5; no initialization is done for the void() case).
Здравствуйте, Vlad_SP, Вы писали:
V_S>Здравствуйте, Сыроежка, Вы писали:
А>>>
А>>>String *newString = new String ("str");
А>>>delete newString;
А>>>
С>>Если оператор new отработал некорректно, то он сгенерирует исключение. Поэтому действительно вызов затем delete newString; является неопределенным поведением, если до этого вы не присвоили этому указателю нулевое константное значение.
V_S>Если оператор new в этом коде выбросит исключение, до выполнения delete newString дело даже не дойдет. Так что неопределенного поведения не будет.
Вопрос о том, что программист сам может вызвать delete, а не о том, что компилятор будет делать delete.
Здравствуйте, Vlad_SP, Вы писали:
V_S>Здравствуйте, Сыроежка, Вы писали:
V_S>дык, в этом коде программист именно сам вызывает delete. И тем не менее, неопределенного поведения нет.
Причем здесь этот код?! Это условный пример, демонстрирующий наличие вызовов. Предложение с delete может стоять в любом месте. Вопрос стоит о том, можно ли вызывать delete или нет, и к каким последствиям это приведет.
— Допустим, у нас имеется такой код:
String *newString = new String ("str");
Если оператор new отработал некорректно, то вызов
delete newString;
вызовет UB, ведь так?
Здравствуйте, Vlad_SP, Вы писали:
V_S>Здравствуйте, Сыроежка, Вы писали:
V_S>вернемся к исходному вопросу: V_S>
— Допустим, у нас имеется такой код:
V_S>String *newString = new String ("str");
V_S>Если оператор new отработал некорректно, то вызов
V_S>delete newString;
V_S>вызовет UB, ведь так?
Ты действительно не видишь разницы в коде?
Разумеется, во втором варианте будет UB. Но это — твой вариант кода, а не тот код, о котором спрашивал TC; и давай не будем домысливать за топикстартера варианты (сферического) кода (в вакууме). ТС спросил о конкретном коде (и привел этот код), порождает ли он UB. Ответ — нет. Если ты считаешь иначе — попробуй в варианте ТС (до/на)писать код, порождающий UB — конечно же, без нечестных приемов вида