удалить кут;удалить cin;не дают ошибку компиляции - недостаток в стандартной библиотеке? - PullRequest
14 голосов
/ 17 сентября 2011

Будет ли следующее приводить к ошибке компиляции?

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 *' не определено

, которого вы можете легко избежать просто приведя, скажем, к char*.Но у программы все еще есть проблема, и, скорее всего, она будет зависать при ее запуске.

-

Итак, мой вопрос, была ли эта проблема решена и исправлена ​​в C ++ 11?В следующей статье приведено одно исправление этой проблемы:

-

Редактировать:

Из комментария @ Xeo к ответу @ Alf:

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

Ответы [ 2 ]

18 голосов
/ 17 сентября 2011

Это, по-видимому, исправлено.

По крайней мере, в N3290 вместо этого void* преобразование std::basic_ios::operator bool, и этот operator bool объявлен explicit.

Обратите внимание, что C ++ 98 / C ++ 03 не поддерживает explicit операторы преобразования типов, но C ++ 11 поддерживает.

explicit оператор преобразования типов

N3290 §12.3.2 / 2;
рассматривается только как определяемое пользователем преобразование для прямой инициализации (8.5)

И этоможет показаться непрактичным для условия , например, в выражении 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.,

0 голосов
/ 17 сентября 2011

Если я могу дать свои 2 цента, я думаю, что стандартная библиотека немного "испорчена" со всеми благими намерениями.

operator void*() был введен, чтобы разрешить код типа while(stream) или if(!stream) или while(stream && ...), без предоставления неявного доступа к целочисленной арифметике (которую бы дал operator bool).Фактически, это отключает целочисленную арифметику, но дает доступ к функциям указателя (например, delete ...).

Теперь, в C ++ 0x, введено explicit oeprator bool().Неявно не дает доступа к какой-либо функции, поскольку требует неявного преобразования.Но ... подождите немного: 'while (bool (stream))' или даже while(static_cast<bool>(stream)) настолько многословны ... Оператор!является явным, и 'while (!! stream)' выглядит настолько эффективным, что я даже удивляюсь, почему бы не принять это как парадигму:

Если я хочу, чтобы что-то было явно преобразовано в bool, я просто предоставляю operator!() и присвойте ! значение «недопустимо» и !! как «допустимо».

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...