Delete cout; удалить cin; не дают ошибки компиляции - недостаток в стандартной библиотеке?
Будут ли следующие ошибки компиляции?
delete cout;
delete cin;
Ответ: Нет.
Это недостаток в реализации классов потоков из стандартной библиотеки. Они имеют следующую функцию преобразования для void*
, что означает, что все объекты потока могут быть неявно преобразованы в void*
:
operator void * ( ) const;
Это очень полезно в целом, поскольку позволяет нам писать очень идиоматический цикл, скажем, при чтении ввода из файлов. Но в то же время он позволяет пользователю писать delete stream
. Как я уже сказал, вы можете удалить любой объект потока. Таким образом, все это разрешено:
delete ss; //declare std::stringstream ss;
delete iss; //declare std::istringstream iss;
delete oss; //declare std::ostringstream oss;
Только они дадут предупреждение, сказав (см. ideone):
предупреждение: удаление 'void * - undefined
который вы можете легко избегать, просто произнося, скажем, char*
. Но программа все еще проблема, и, скорее всего, произойдет сбой при ее запуске.
-
Итак, мой вопрос в том, была ли эта проблема решена и исправлена, в С++ 11? В следующей статье приведено одно исправление этой проблемы:
-
Edit:
От комментария @Xeo от ответа @Alf:
В документе, в котором предлагается исправление этой проблемы:
Ответы
Ответ 1
Он, по-видимому, был исправлен.
По крайней мере, в N3290 вместо void*
преобразование std::basic_ios::operator bool
и operator bool
объявлено explicit
.
Обратите внимание, что С++ 98/С++ 03 не поддерживает операции преобразования типа explicit
, но С++ 11. делает.
Оператор преобразования типа explicit
N3290 §12.3.2/2;
рассматривается только как пользовательское преобразование для прямой инициализации (8.5)
И это может показаться непрактичным для условия, например. a while
или for
.
К счастью,
N3290 §4/3;
Выражение e
может быть неявно преобразовано в тип T
тогда и только тогда, когда декларация T t=e;
хорошо сформирована для некоторой изобретенной временной переменной T
(8.5). Для некоторых языковых конструкций требуется, чтобы выражение было преобразовано в логическое значение. Выражение e
, появляющееся в таком контексте, называется контекстно преобразованным в bool
и хорошо сформировано тогда и только тогда, когда декларация bool t(e);
хорошо сформирована для некоторой изобретенной временной переменной T
(8.5), Эффект либо неявного преобразования является таким же, как выполнение декларации и инициализации, а затем используя временную переменную в результате преобразования.
где bool t(e);
- прямая инициализация.
например. вы не должны явно преобразовывать объект потока, используемый в качестве условия в while
, потому что явно подразумевается явное преобразование (он он).
К сожалению, при поиске N3290 я не могу найти какой-либо список "определенных языковых конструкций", где это происходит, но в комментариях к этому ответу JohannesD писал:
Искал через FDIS для "контекстуально", и весь список выглядит следующим образом: if
, while
, do
, for
, noexcept
и static_assert
; первый операнд ?:
; и то и другое операнды &&
и ||
; и операнд !
.
Приветствия и hth.,
Ответ 2
Если я могу дать свои 2 цента, я думаю, что стандартная библиотека "немного испорчена" со всеми благими намерениями.
Был введен operator void*()
, чтобы разрешить
while(stream)
или if(!stream)
или while(stream && ...)
, без предоставления неявного доступа к целочисленной арифметике (это operator bool
, которое вы указали).
Фактически, это отключает целочисленную арифметику, но дает доступ к функциям указателя (например, delete...).
Теперь, в С++ 0x, был введен a explicit oeprator bool()
. Он не подразумевает доступ к любой функции, поскольку требует неявного преобразования. Но... подождите немного: 'while (bool (stream))' или даже while(static_cast<bool>(stream))
настолько многословны...
Оператор! является явным, и
'while (!! stream)' выглядит настолько эффективным, что я даже удивляюсь, почему бы не принять это как парадигму:
Если я хочу, чтобы что-то было явно преобразовано в bool, я просто предоставляю operator!()
и дайте !
сохранение "недопустимо" и !!
как "действительно".
Гораздо безопаснее, чем неявное преобразование, а не бесполезно многословное: ведь !
существует из когда-либо!