Привет всем. В книге Липмана "C++ для начинающих" сказано примерно следующее: Он пишет, что предлогалось ввести в стандарт расширение преодолевающее это препятствие, но оно не прижилось. С другой стороны существует оптимизация этого дела, когда вызов функции трансформируется из Код (Text): retClass foo() в Код (Text): foo( retClass &obj ) Что конечно-же гораздо эффективнее. Ещё Липман пишет, что для этого нужно в функции всегда возвращать только один объект (в разных return). Смотрю в VC 2003 и вижу, что даже если возвращаются разные экземпляры, то всё равно функция оптимизируется. Засим вопрос. Как эта оптимизация регламентируется стандартом, и корректно ли поступает в этом случае VC 2003?
Кто это такой? Очередной аффтар? )) В 2009-м стандарте будут какие-то move-конструкторы. Возможно они решат проблему. Но не будем забывать, что во-первых, это называется преждевременной оптимизацией, во-вторых, foo( retClass &obj ) не безопасна с точки зрения исключений. Люди, которые на первое место ставят производительность, никогда не научатся программировать.
_DEN_ Насколько мне известно этот чел работал со Страструпом. И вообще известный автор и в 3D графике. Поподробнее мона? Какой толк от программы которая жутко тормозит. С++ и задумывался как язык высокоэффективный, отсюда и его многие проблемы.
Booster Все понятно))) Первый раз слышу. 1% оверхеда как плата за безопасность и стабильность это более чем приемлемо. Мало ли как он там задумывался. С++ это уже давно не Страуструп и не какой-то конкретный человек. С++ сегодня и 10 лет назад - это два совершенно разных языка. Код (Text): int x = 0; .... .... foo(x); void foo(int& x) { x = 10; throw std::out_of_range(); x = 20; }
Пример боюсь не дойдет. Вот более наглядно: Код (Text): void ReadData(File& file) { file.Open(); file.Read(); file.Validate(); throw ...; file.Close(); }
не понял? а чем поможет конструктор копирования в ретурне? - я уже заколустался от игрушек, тормозящих на 3 Гц с гигабайтовыми мозгами весом в десятки мегабайт, повторяющие функциональность досовских игр с немного улучшенной графикой. иногда не думают даже о самой очевидной оптимизации, типа выноса инвариантных действий за пределы цикла..
Ну подумай: Код (Text): File ReadData() { File file; file.Open(); file.Read(); file.Validate(); throw ...; file.Close(); return file; } На эту тему я даже спорить не буду. Вообще не буду.
_DEN_ Не дошло и сейчас. Кто мешает перехватить все исключения в блоке, затем в его обработчике сделать необходимую очистку, и снова инициировать исключение. Но всё же это не совсем в тему. Спорить о том надо ли передавать значение или ссылку, не совсем корректен. Есть случаи когда издержки 1% процент, а есть когда 100%. Вопрос в том как это регламентирует стандарт, и чего нужно от этого ожидать. Хотя если есть какие-то проблемы (опять таки например исключения), то тогда хотелось бы как-нибудь управлять процессом оптимизации. Да и всё же, объясни популярно в чём трабла с исключениями?
_DEN_ деструктор (если я тебя правильно понял) должен по-хорошему выполнять действия, обратные конструктору. рассчитывать на полную очитку после всех действий только в деструкторе, без явного вызова методов, неправильно само по себе. хотя иногда себя оправдывает. по крайней мере, я так считаю
Booster Все понятно. Ты просто не знаешь что такое "код безопасный с точки зрения исключений". После вышеуказанной цитаты это не реально)). Nouzui Поздравляю тебя. Ты считаешь неправильно.
_DEN_ нну ладно.. давай рассмотрим конкретно.. итак, твой File - класс, оборачивающий работу с файлами. Возьмем для начала windows и апи. поехали.. class File { HANDLE hFile; .... }; File::File(): hFile(INVALID_HANDLE_VALUE) {}; какой-то тип File::Open(...) { #if DEBUG if(hFile!=INVALID_HANDLE_VALUE) .... #endif hFile= CreateFile(...); if(hFile==INVALID_HANDLE_VALUE) кстати, что должно быть здесь, на твой взгляд? ... } Read и Validate сам напишешь. кстати, что такое Validate? void, наверное File::Close(...) { #if DEBUG if(hFile==INVALID_HANDLE_VALUE) ... #endif CloseHandle(hFile); hFile= INVALID_HANDLE_VALUE; } File::~File() { if(hFile!=INVALID_HANDLE_VALUE) Close(); } так все?
_DEN_ Признаюсь не знаю, но догадываюсь. Конечно в варианте со ссылкой освобождение ресурсов автоматически не произойдёт, и это безусловно плохо. Но всё же правильно разрулить эту ситуацию имхо возможно. Так как дефолтовый конструктор генерировать исключения не должен, и память под объект выделяется заранее, то у этого объекта можно самим вызвать деструктор, хотя безусловно всё это не очень здорово, но имхо работоспособно, тем более что не всегда исключения нужны.
Booster судя по всему вопрос не об оптимизации кода программером (с учетом или без влияния на него исключений), а об оптимизации кода на этапе компилирования. ISO C++ раздел 12.8 пункт 15 похоже VC прав.
RedLord Совершенно верно. Хорошо что это стандартизировано. Но по поводу: Все же не понятно. Если мы возвращаем один объект, тогда мы вызываем конструктор по ссылке, делаем с ним чо-то и в конце спокойно забываем о нём. Но если у нас произошла промашка и у нас возвращается в итоге другой объект, конструктор копирования всё равно должен вызваться. Вся оптимизация есно на смарку. Получается что когда-то возможна оптимизация, а когда-то и нет, а это IMHO не хорошо. По идее это жёстко должно быть прописано, иначе возможно непредвиденное поведение.
RedLord Ну вот такое Код (Text): RetClass foo() { RetClass obj; ret obj; } RetClass obj = foo(); превращается компилятором в Код (Text): foo(&obj) { obj.constructor(); } выделяется неинициализированная память под RetClass obj. foo(&obj); Внутри foo срабатывает конструктор для obj. Но если мы возвращаем в разных случаях разные объекты, то получаеся облом, а студия всё равно оптимайзит. И не ясно как тут нужно оптимайзить, и как тут стандарт регламентирует, то есть когда у нас есть в функции несколько return c разными объектами. Получается то оптимизация сработает, а то нет, не ясность.
Booster насколько я понял ты говоришь о такой варианте кода Код (Text): struct A { A(int x); }; A foo(bool flag) { if (flag) { return A(1); } return A(5); } я не знаю, как разрабы компилеров реализуют указанный пункт Стандарта, но никаких проблем, с точки зрения компилера, для оптимизации кода я не вижу. в любом случае - экспериментируй. разрабы компилеров не всегда блюдят Стандарт.