Подтвердить что ты не робот

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:

В документе, в котором предлагается исправление этой проблемы:

4b9b3361

Ответ 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!() и дайте ! сохранение "недопустимо" и !! как "действительно".

Гораздо безопаснее, чем неявное преобразование, а не бесполезно многословное: ведь ! существует из когда-либо!