В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
Здравствуйте, ilya123, Вы писали:
I>В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
NULL это традиция.Нулем он и определен — а в чем проблема?
Насчет, сразу или после определять переменную, так это дело практики или личных присрастий, делайте как Вам угодно, только делайте это, того требует элементарная аккуратность. Первый вариант мне нравитсться больше.
Здравствуйте, ilya123, Вы писали:
I>В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
Обрати внимание: большинство примеров по API написаны на С, а не на C++.
Здравствуйте, ilya123, Вы писали:
I>В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
Про C уже сказали. Я использую 0 вместо NULL — мне так больше нравится.
Что касается объявления переменных перед использованием, то лучше действительно объявлять перед использованием. "Расстояние" (в SLOC обычно) между объявлением переменной и первым ее использованием назвается "пробегом" и учитывается в некоторых метриках "поддерживаемости" и "надежности" кода. Чем меньше суммарный пробег по программе, тем лучше.
Здравствуйте, Xentrax, Вы писали:
X>Про C уже сказали. Я использую 0 вместо NULL — мне так больше нравится.
Дело вкуса, хотя NULL — это указатель, а 0 — это в том числе и число.
Просто чтобы не было путаницы...
X>Что касается объявления переменных перед использованием, то лучше действительно объявлять перед использованием. "Расстояние" (в SLOC обычно) между объявлением переменной и первым ее использованием назвается "пробегом" и учитывается в некоторых метриках "поддерживаемости" и "надежности" кода. Чем меньше суммарный пробег по программе, тем лучше.
А также от конструирования до первого использования и от последнего использования до деструирования.
Особенно это существенно для объектов.
Здравствуйте, ilya123, Вы писали:
I>В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
Я считаю что надо обьявлять перед использованием и по возможности инициализировать осмысленно(не 0).
те
Type* ptr=new Type();
а не
Type* ptr=0;
ptr=new Type();
Если мы говорим о С++ то надо обязательно заворачивать в умный указатель
T_SmartPtr<Type> ptr=new Type();
Если планируется использование указателя за пределами функции то надо использовать указатель с подсчетом ссылок
Например есть оч тажолый обьект который создается в функции.
Ессно нельзя сохранить указатель во внешних переменных если не гарантируется что обертка не бедет разрушина
Type* ptr=0;
{
T_SmartPtr<Type> sptr=new Type();
ptr=sptr;
}//здесь обьект будет удален и ptr стенет инвалидным
void foo(Type* p)
{
//.....
}
void bar()
{
T_SmartPtr<Type> ptr=new Type();
foo(ptr);
}//здесь обьект будет удален после выхода из foo и проблем не возникнет
Но я рекомендую T_SmartRefPtr ибо если вдруг реализация foo будет изменена и она сохранит указатель то AV неизбежин.
//Передача по ссылке ибо T_SmartRefPtr хотя и легок но лишние копирование не нужноvoid foo(const T_SmartRefPtr<Type>& p)
{
//.....
}
void bar()
{
T_SmartRefPtr<Type> ptr=new Type();
foo(ptr);
}//теперь если foo сохранит указатель то сдесь удаление обьекта не произойдет
Итого:
Плюсы вероятность ошибки _значительно_ снижается ибо не надо думать о пролетающих исключениях, выходить из функции можно когда вздумается и не писать код освобождения ресурсов что приводит к болие короткому и читабельному коду.
Минусы T_SmartPtr и T_SmartRefPtr те нельзя передать обьект из одного другому вернее из T_SmartPtr в T_SmartRefPtr теоритически возможно но крайне не рекомендую так поступать, а обратно нельзя ибо неивестно сколько указателей на обьект существует.
ибо гарантировано будет попытка дважды удалить этот обьект и наверняка попытка доступа к мертвому обьекту.
ессно так тоже ни чего хорошего не получится
T_SmartRefPtr<Type> ptr=new Type();
delete ptr;
Заключение: Не смотря на появление новых опасностей рекомендую к использованию ибо наступить на них много сложнее чем забыть освободить память или закрыть фаил.
... << RSDN@Home 1.0 beta 4 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Все чересчур сурово смарт-указатели, приведения указателей и прочее. Мне не нравиться ... а вообще все здорово! До Элджера я все это видел у Borland-а в BC4.0. Инклюд потешно назывался <owl/pointer.h>, я тогда все понять не мог почему он так называется. В то время ребята Borland-a творили чудеса.Когда понял как работают смарт-указатели (это их сейчас так называют/умных книжек было мало) ходил в одурении месяца два, засовывал их во все места. Сегодня это как мат двумя слонами — скучно и банально.
Здравствуйте, Кодт, Вы писали:
К>А также от конструирования до первого использования и от последнего использования до деструирования. К>Особенно это существенно для объектов.
Здравствуйте, WolfHound, Вы писали:
WH>Если мы говорим о С++ то надо обязательно заворачивать в умный указатель WH>
WH> T_SmartPtr<Type> ptr=new Type();
WH>
Речь идет о какой-то конкретной библиотеке или T_SmartPtr — обобщенное имя?
Просто мне хочется в проекте использовать смарт-указатель (не COM) попрямее (не такой, как std::auto_ptr).
Пока нравится только boost::shared_ptr. Еще есть идеи?
Здравствуйте, UgN, Вы писали:
К>>А также от конструирования до первого использования и от последнего использования до деструирования. К>>Особенно это существенно для объектов.
UgN>А вот так (не)хорошо делать?
UgN>Таким образом ведь можно существенно уменьшить расстояние от конструирования до деструктирования?
Если объект громоздкий — то я бы очень и очень рекомендовал.
Потому что разбираться в мышиной возне, начинающейся при выходе из функции — особо мучительно.
Если это (умный) указатель / хэндл ресурса — то хотя бы обнулять его после использования (что вызовет освобождение объекта/ресурса сразу же).
Здравствуйте, Владик, Вы писали:
В>Почему бы тогда не написать:
В>
В> ClassA().method();
В> ClassB().method();
В>
Ну а если не один метод вызывается, а несколько?
В>А если использование каждого из классов более сложное, то вынести работу с ними в отдельные функции?
А если не настолько сложное, чтобы выносить в отдельную функцию?
Здравствуйте, UgN, Вы писали:
В>>А если использование каждого из классов более сложное, то вынести работу с ними в отдельные функции? UgN>А если не настолько сложное, чтобы выносить в отдельную функцию?
Здравствуйте, retalik, Вы писали:
WH>>Если мы говорим о С++ то надо обязательно заворачивать в умный указатель WH>>
WH>> T_SmartPtr<Type> ptr=new Type();
WH>>
R>Речь идет о какой-то конкретной библиотеке или T_SmartPtr — обобщенное имя? R>Просто мне хочется в проекте использовать смарт-указатель (не COM) попрямее (не такой, как std::auto_ptr). R>Пока нравится только boost::shared_ptr. Еще есть идеи?
Я для себя написал и давно использую такие макросы:
Привет, ilya123!
I>В примерах от MS все переменные объявляются в начале функции и используется NULL. Хотя Страуструп советует объявлять переменные только перед использованием и вместо NULL использовать 0. Кто прав? Интересует этот вопрос применительно к кодированию под Windows.
Что касается стиля программирования, то здесь каждый сам себе хозяин.
Для себя я давным-давно сформулировал одно простое правило, успешно корректирующее мой собственный стиль написания программ: программа пишется для того, чтобы она работала.
Первое, что из этого вытекает, это то, что код должен быть удобочитаемым. В этом и только в этом случае его можно будет всегда успешно подправить или дописать, найти ошибку и т.п. Поэтому для инициализации указателей нулем я обычно всегда пишу явный 0, указывая явным образом в скобках тип, хотя стандарт этого делать не требует: (type *)0.
Что касается переменных, то мое глубокое убеждение, точнее жизненный опыт, говорит о том, что описание переменных по ходу текста функции — одно из главных преимуществ C++ перед Паскалем. Почему? Очень просто: 1. Локализация переменных. Возможность использования переменной в явном контексте функции, избегая ее использования (в том числе и случайного — сколько раз такое было!) вне конкретного блока, цикла и т.д. 2. Оптимизация. Возможность создания и уничтожения классов, структур, их экземпляров, переменных и т.п. в нужных местах, т.е. экономия памяти, времени, оптимизация и т.п. 3. Удобочитаемость. Если переменная i используется только в цикле, так давайте использовать ее только там. В пользу этого говорят оба предыдущих пункта. Кроме того, в начале функции рекомендуется собирать только те объявления, которые наиболее существенны для всей функции, отражают ее смысл и вариант реализации. Какой автор театральной пьесы будет вписывать в "действующие лица" всех собак и кошек, участвующих в действии, или молчаливого кучера?
Одним словом, при разумном использовании возможностей C++ код становится более ясным для понимания. Так почему этим не пользоваться?
Здравствуйте, retalik, Вы писали:
R>Речь идет о какой-то конкретной библиотеке или T_SmartPtr — обобщенное имя?
Это обобщенное имя.
R>Еще есть идеи?
Я их сам пишу.
И что же получается? Мы передаем в конструктор указатель CMyObject*, там он сохраняется в void* и потом удаляется, как void*.
Разве можно это назвать правильным?
A>...
A>Для себя я давным-давно сформулировал одно простое правило, успешно корректирующее мой собственный стиль написания программ: программа пишется для того, чтобы она работала.
A>Первое, что из этого вытекает, это то, что код должен быть удобочитаемым...
Увы! Из первого утверждения второе не "вытекает". Даже, более того, именно работоспособность неудобочитаемого (для человека) кода и усугубляет проблему. Ибо компилятору до лампочки удобочитаемость, или структурированность, или соответствие каким-то корпоративным правилам, т.е. то, что выходит за рамки синтаксиса языка.
Поэтому лучше говорить:"Код программы пишется для чтения его в первую очередь человеком, а потом только компилятором".