Б. Страуструп - Дизайн и Эволюция C++. 2006 (1160775), страница 40
Текст из файла (страница 40)
Такой код распространен широко, и даже те реализации, в которых обычно выдержана стратегия немедленного уничтожения, например б)ч() С++, стараются в подобных случаях отложить его. Размышления в этом русле натолкнули меня на мысль уничтожать временные объекты в конце предложения, в котором о~и были сконструированы. Тогда приведенный выше пример был бы не только корректным, но и гарантированно переносимым. Однако при этом перестали бы работать другие, «почти эквивалентные» примеры: Стандартизация ПИФИИ ИИ!1 Оставляю подбор аргументов в пользу каждого варианта в качестве упражнения для читателя. Однако можно найти и серьезные возражения против каждого из указанных подходов. Следовательно, необходимо выбрать вариант с оптимальным сочетанием преимуществ и недостатков. Мы также рассматривали возможность разрушения временного объекта после его последнего использования в блоке.
Но это потребовало бы анализа потока выполнения, а у нас не было уверенности, что любой компилятор сможет провести такой анализ достаточно надежно, чтобы точка «за последним использованием в блоке» означала бы в любой реализации одно и то же. Отмечу, что локального анализа потока недостаточно для предотвращения «преждевремснного уничтожения», например потому, что конверторы, возвращающие указатель на внутреннюю область объекта, часто определяются не в той единице трансляции, в которой используются. Попытка запретить такие функции не имела смысла, так как при этом перестало бы работать слишком много программ.
Да и контроль над ситуацией был невозможен. С 1991 г. комитет склонялся к варианту «конца предложения». В обиходе он получил название ЕОВ гепд о('з(агешепс). Оставалось точно определить, что" же такое «конец предложениям Рассмотрим пример: чоЫ Ь(эгггпд в1, Ясггпд в2) ( сопев сваг* р; 1г (р = в1+в2) ( // ) Будет ли значение р использоваться внутри предложения блока? Иначе говоря, нужно ли уничтожать объект, содержащий в1+в2, в конце условия или в конце всего предложения И? Ответ: объект, содержащий в1+в2, будет уничтожен в конце условия.
Было бы абсурдно гарантировать что-то относительно предложения (р = в1+в2) рггпсс( «в',р); оставляя р = в1+52; рг1пгг("Ъв",р); зависящим от реализации. Как следует обрабатывать ветвления внутри выражения? Например, должно ли гарантированно работать такое предложение: 11 ((р = в1+в2) ьв р(0)) ( // ) Да, должно. Но гораздо проще привести готовый ответ, чем объяснить специальные правила для йй, ( ( и 2:. Против этого предложения выдвигались возражения, 11ИИИИИКИ Расширения поскольку чаше всего его невозможно реализовать, не вводя флаги, гарантирующие, что временный объект уничтожается, только когда он появился именно в той ветви, по которой пошло выполнение.
Однако разработчики компиляторов ответили на вызов и продемонстрировали, что возникающие затраты чрезвычайно малы. Таким образом, ЕОБ стало означать «конец полного выражения», где под полным выражением понималось выражение, не являющееся подвыражением другого выражения. Разрешив уничтожать временные объекты в конце полного выражения, мы «разрушили» некоторые программы, компилировавшиеся ранее С1гопц но все гарантии, предоставленные АКМ, были сохранены. Принятое решение отражает желание иметь четко определенное и легко поддающееся объяснению местоположение точки уничтожения. Оно также согласуется с желанием не хранить временные объекты слишком долго.
Объекты, которые должны существовать дольше, надо именовать, или использовать приемы, не требующие долгоживущих временных объектов. Например: чоЫ Г(эгг1лд в1, Ягг)лд е2) ( рг1лг1("«е", я1+в2); // правильно сопел слег* р = е1+е2; рг1лсс("«в", р); О не работает, временный объект уничтожен Згг1ля вЗ = е1+Б2г рг1псс("«я", (сонет слег*)еЗ)) // правильно сонг « еЗ; // правильно сонг « е1+е2г // правильно 6.4. Расширения Исключительно важным был и остается вопрос о том, как справиться с нескончаемым потоком предложений об изменениях и расширениях языка.
Основная роль при его решении отводится рабочей группе по расширениям, в которой я являюсь председателем. Любое предложение гораздо проще принять, чем отвергнуть. Так вы приобретаете друзей, а люди ценят язык, в котором много «полезных штучек». Однако язык, построенный как конгломерат средств, внутренне не связанных между собой, неудачен, поэтому нет никакой возможности принять даже большую часть средств, которые были бы по-настоящему полезны той или иной части сообщества пользователей С++.
На вышеупомянутой встрече в Лунде была очень популярна такая история [Ягопзггцр,1992Ь): «Мы часто вспоминаем о прекрасном корабле «Чазов. Он был гордостью шведского Военно-морского флота, самым большим и красивым из когда-либо построенных военных судов. К сожалению, во время строительства в проект были внесены существенные изменения, поскольку НИИИИИВВ Стандартизация в первоначальном варианте не было предусмотрено места для всех статуй и пушек, которые хотели установить на корабле. Не успело судно доплыть до середины Стокгольмской бухты, как налетевший порыв ветра перевернул его, и примерно пятьдесят человек погибли.
Корабль подняли со дна, и теперь на него можно посмотреть в музее Стокгольма. Он прекрасен - гораздо красивее, чем был бы оригинальный, выполненный по первоначальному проекту, и уж, конечно, много красивее того, во что бы он превратился, вели бы разделил обычную судьбу военных кораблей семнадцатого века. Но вряд ли это может служить утешением для инженеров, строителей и моряков, которые так и не смогли увидеть «Чаза» в деле».
Зачем вообще рассматривать расширения7 Ведь Х3116 — это комитет по стандартизации, а не группа проектирования, которая обязана разработать язык «С+++»». Да и не может коллектив из 250 человек с переменным составом надеяться на успех в области проектирования языка. Поначалу группе было поручено заняться шаблонами и обработкой исключений. Но еще до того как комитет приступил к работе, на его представителей посыпались предложения о расширениях и несовместимых изменениях.
Пользователи, даже те из них, кто сам ничего не предлагал, ждали, что комитет предложения рассмотрит. Если комитет принимает такие предложения всерьез, а это обычная практика, он становится центром дискуссий по поводу будущего С++. Если же не обращать внимания на чьи-то инициативы, то атот центр просто переместится в другое место, что приведет к появлению несовместимых расширений. Кроме того, многие любят новые возможности, хотя публично расписываются в преданности минимализму и стабильности.
Проектирование языка — само по себе интересное занятие, дебаты вокруг новых возможностей стимулируют воображение и служат хорошим поводом для написания статей и выпуска новых версий. Поэтому я предпочитаю сдать выход пару», извлекая из этого конструктивные преимушества. Итак, у комитета был выбор: обсуждать расширения, рассматривать диалекты уже после их появления или игнорировать ситуацию. Подобие дилеммы вставали перед разными комитетами по стандартизации, и каждый принимал свое решение. Большинство, в том числе комитеты по языкам Аг1а С, СоЬо1, Гогтгап, Мог1п!а-2 и Рааса!-2, решали вопрос в пользу рассмотрения расширений.
Я уверен, что стремление добавить языку то или иное расширение неизбежно, и лучше, чтобы это происходило открыто, на публичном форуме, где есть хоть какие-то формальные правила. Альтернатива — схватка за признание собственных идей через привлечение на свою сторону пользователей на рынке. Такой механизм не способствует спокойным размышлениям, открытым дискуссиям и попыткам удовлетворить потребности всех пользователей. В результате мы получаем язык, распавшийся на диалекты.
Очевидные опасности, присущие рассмотрению указанного вопроса, лучше, чем хаос, который воцарится в противном случае. Большинство членов комитета согласилось со мной, но мы шли к той точке, когда работа над расширениями в том виде, в котором она ведется сейчас, должна была прекратиться, поскольку приближался момент принятия стандарта и все направили усилия на его критическое изучение.
Расширения ЯИИИИИИБ Со временем кто-то переключился на другие языки, кто-то занялся экспсриментальной работой, кто-то посвятил себя созданию библиотек. Интересно отметить, что группы по стандартизации, как и любые другие организации, расформировываются с большой неохотой. Часто такая группа возрождается, пусть даже в виде бюрократического механизма для создания стандарта следующего уровня, то есть комитета по проектированию нового языка или диалекта. Примерами подобного явления служат комитеты цо языкам А1яо!, Гогггап, Рааса! и даже АХБ1 С.
Тем временем я стараюсь обезопасить себя от попыток проектирования чсголибо самим комитетом, посвящая много времени каждому поступившему предложению. Стратегия эта хоть как-то защищает от принятия взаимоисключающих средств, и язык, возможно, не утратит внутреннюю целостность. Комитет легко может угодить в ловушку и одобрить нскоторую возможность просто потому, что кто-то настаивает на ее необходимости. Всегда проще отстаивать полезность того или иного средства, чем доказывать, что его преимущества— возможно, на самом деле очень важные — не навредят внутренней логике, простоте и стабильности языка. Кроме того, в комитете не склонны прислушиваться к аргументам, основанным на экспериментах и опыте.
Видимо, когда решения принимаются путем голосования, лучшими аргументами являются те, что легче усваиваются уставшими представителями комитета. Таким образом, чстандартизация» может стать источником нестабильности. Всегда есть опасность, что принятое изменение будет совершенно случайным или даже никуда не годным. Чтобы не допустить этого, к стандартизации надо приступать на подходящей стадии эволюции языка, когда пути развития четко определены, а диалекты, поддерживаемые солидными коммерческими структурами, еше не успели появиться.
Я надеюсь, что для С++ момент был выбран правильно и комитет будет и дальше проявлять необходимую консервативность в отношении нововведений. Стоит напомнить, что некоторые пользователи обходятся и вовсе без расширений. Поборники новых возможностей как-то забывают, что хорошую программу можно построить и без изощренной языковой поддержки. Никакое отдельное средство не является необходимым для проектирования симпатичной программы, даже такое, без которого мы не мыслим своей работы. Удачную программу можно написать и на С, и на небольшом подмножестве С++.