Я думаю, что можно обсуждать вопросы без проставления нулей, тем более что исходный ответ TepMuHyc не заслуживал такой оценки изначально — он никому не грубил, не хамил, не навязывал свою точку зрения и т.п. Если уж, уважаемый Zilog™, имеете претензии лично к TepMuHyc, то перейдите на личную переписку и выскажите там все.
А теперь по сути разборки.
То, что вы начали обсуждать — это дело вкуса, принятых в кампании правил и т.п., и тут уж каждый будет считать своё решение единственно правильным.
С++ даёт 4 возможности передачи параметра не по значению: ret_type func( type* ptr );
ret_type func( type& ref );
ret_type func( const type* cptr );
ret_type func( const type& cref );
Первые два дают право изменять параметр, вторые (при хорошем стиле) — нет. Всё! Обсуждать здесь даже нечего.
Вы имеете полное право и возможность пользоваться всеми этими способами без ограничения со стороны компилятора или со стороны стандарта, если учесть пропускаемую некоторыми компиляторами недопустимость ссылки на пустой объект.
Поэтому вы вольны выбирать по своему вкусу правила записи функций, изменяющей свои параметры, и требовать их выполнения в своей компании, и никто не должен осуждать вас за это.
Однако, было бы неплохо учитывать проверку компилятора при указании ключевого слова const и/или указывать информацию об изменении параметров в названии функции. Опять же это дело вкуса.
PS
Обычно советы использовать то-то и то-то носят характер рекомендаций.
Поэтому и нужно писАть: Как правило, ссылки используются ..., указатели используются ...
А требования использовать то-то и то-то носят характер обязанности.
Поэтому и нужно писАть: Вы должны использовать ссылки ..., а указатели — ...
Здравствуйте SergH и Зилог, Вы писали:
TMH>>2) Программист не желает читать документацию. В этом случае его умственные SH>3) Документация отсутствует или она очень плоха.
...Но заголовки-то есть ?
SH>Код, применяющий указатели проще для понимания.
Ты не забыл добавить ИМХО?
SH>По-моему с этим спорить трудно.
Напиши Страуструпу. Он довольно охотно отвечает на умные письма. И с ним даже можно поспорить.
А вот переспорить — трудновато...
...Это была преамбуда. Теперь амбула.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
То ли ссылки, то ли указатели — зависит от многого — legacy code, корпоративный/командный стиль кодирования, личные предпочтения и т.д. Короче — случаи бывают разные и вариантов много. И все они заслуживают уважения.
Лично я более склоняюсь к использованию ссылок — считаю это "хорошим тоном" в C++...
Теперь по "классам":
Указатели (плюсЫ)
1) C-only код весьма распространен — в особенности на Юнихах. Т.к. ссылок в С нету создается иллюзия что с одними указателями жизнь хороша.
2) Когда приходится писать DLL или Shared Library, то хороший тон экспортировать функции в соглашениях С — чтобы данная библиотека была двоично совместима с разными компиляторами.
3) При вызове функций в списке параметров явно виден оператор адресации.
Указатели (минусЫ)
1) Очень легко создать некорректный указатель "случайно" — достаточно забыть его проинициализировать.
2) Они весьма непонятны новичкам переползшим на C++ с Java/Basic/Pascal
3) При вызове функций в списке параметров явно виден оператор адресации. Но далеко не всегда. Для того чтобы _всегда_ корректно его пременять надо быть с адресной арифметикой более на "ты"...
Ссылки (плюсЫ)
1) Очень трудно создать некорректрую ссылку "случайно"
2) Паскалистам и Визуальным Басикерам ссылка как аргумент функции близка и понятна.
3) Ссылка как аргумент функции не нуждается в проверке ее корректности.
4) Страуструп рекомендует ее использовать взамен указателя.
Ссылки (минусЫ)
1) "Упертые сишники" ни в зуб ногой не понимают зачем она нужна.
2) см. Указатели (плюсЫ) пункт 2
2) см. Указатели (плюсЫ) пункт 3 и Указатели (минусЫ) пункт 3
Но ИМО нормальный C/C++ программер должен быть знаком и свободно оперировать обоими.
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Здравствуйте Dr_Sh0ck, Вы писали:
DS>На счет красивше — может быть, однако очень часто рекомендуют делать так: если ф-ция должна изменить передаваемый ей параметр, то лучше передавать его через указатель — так яснее выглядит на передаваемой стороне.
"Так яснее выглядит" для обросших мохом сишников — которые привыкли что единственный способ передачи параметра "по ссылке" — это указатель. А если же параметр надо передать "по ссылке", но менять нельзя — применяется константная ссылка — "const type&"
Чем же ссылка хороша — а тем что, в отличие от указателя, она всегда корректна — то есть нет способа передать пуcтую ссылку. Точнее, он есть, но он требует вполне осознаннах телодвижений — такое по ошибке не сделаешь — в отличие от пустых и некорректных указателей.
Лично я применяю ссылки если мне надо передать параметр "по ссылке" (как вам каламбур?).
Это гарантирует (внутри функции) что данный параметр корректен и, следовательно, избавляет от дополнительных проверок на NULL и т.д.
ЗЫ.НЕ думайте что я против указателей. Они хороши. Но иногда ссылки — в особенности в качестве параметров функций, гораздо хорошее
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Z™>Жестоко это... :no: , таким образом ты запутаешь человека который твой код будет использовать.
Нисколечко. Все что надо — это внимательно читать RTFM :-)
Посмотри документацию по MFC, ATL, STL — как часто там используются указатели?
А ссылки?
Z™>int a = 5;
Z™>SomeFunc(a); // Поменяли "a", но мне об этом надо догадаться.
Теперь другой пример: SomeFunc(5); И что же нам скажет компилятор?
Я думаю выдаст трезвую и взвешенную оценку умственных способностей программиста.
Z™>В этом случае надо параметры каждой используемой функции просматривать.
Их в любом случае просматривать надо перед тем как вызов оной функции писать.
Хотя бы для того чтобы иметь представление что данная функция делает.
То есть, здесь лично я вижу две проблемы:
1) Человек имеет серьезные проблемы с языком С и C++. Т.к. ему трудно
распознать смысл конструкций TYPE* и TYPE&. Пусть учится. Или идет на...
на... На Джаву! :-)
2) Программист не желает читать документацию. В этом случае его умственные
способности а также обстоятельства его зачатия, рождения и воспитания будут
подробно рассмотрены в курилке другими программерами. Или же работодателем...
Z™>int a = 5;
Z™>SomeFunc(&a); // Поменяли a, но я возможность изменения "a" вижу сразу.
...Мне это напомнило набивший оскомину пример со scanf() из справочника Кернигана-Ричи.
Где новичку вбивают в голову "если вы используйте параметр для приема данных,
передавайте в функцию его адрес". С тех времен прошло уже достаточно времени
и были придуманы более удобные конструкции — классы, шаблоны, ах да, еще
и ссылки :-).
Теперь тот же пример немного по-другому: SomeFunc(0); — тоже вполне
корректно, а последствия, думаю, очевидны.
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Здравствуйте Vladik, Вы писали:
V>Кроме того, есть еще одна принципиальнвя разница между ссылками и указателями, — ссылка может быть проинициалзирована только один раз. Т.е.: V>int i1=1, i2=2; V>int &ref1=i1; V> ref1=i2; // после этого ссылка не станет ссылаться на i2, но i1 станет равна 2!!!
Отнюдь.
int i1 = 1, i2 = 2;
int i3 = 3, i4 = 4;
int *ptr = &i1;
int &ref = i3; // это конструктор, а не оператор присваивания
// модификация ссылаемого объекта
*ptr = i2; // ptr == &i1; *ptr == i1 == i2 == 2
ref = i4; // &ref == &i3; ref == i3 == i4 == 4
// модификация ссылки
ptr = &i2;
&ref = &i4;
Считайте, что ссылка — это неявно разыменуемый указатель — и будет вам щастье.
Кстати, передавать ссылку в функцию — означает, что объект существует.
Потому что указатель может быть и нулевым (как вполне осмысленное значение).
Здравствуйте Кодт, Вы писали:
К>Здравствуйте Vladik, Вы писали:
V>>Кроме того, есть еще одна принципиальнвя разница между ссылками и указателями, — ссылка может быть проинициалзирована только один раз. Т.е.: V>>int i1=1, i2=2; V>>int &ref1=i1; V>> ref1=i2; // после этого ссылка не станет ссылаться на i2, но i1 станет равна 2!!!
К>Отнюдь. К>
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Доброго времени суток. АП>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели? АП>Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит.
Я читал кажется у Элджера, что он советует использовать ссылки для лаконичности и простоты. А указатели использовать только тогда, когда передаваемый объект может не существовать (т.к. не может быть ссылки на NULL). Но я предпочитаю (как еще кто-то в этой теме уже писал)использовать указатели, чтоб подчеркнуть, что объект может быть изменен.
Здравствуйте TepMuHyc, Вы писали:
SH>>3) Документация отсутствует или она очень плоха. TMH>...Но заголовки-то есть ?
Понятно, что как бы программа не была написана, если она работает, то возможно разобраться как именно она это делает. Но если можно упростить жизнь и себе и сопровождающему программисту, почему бы этого не сделать?
SH>>Код, применяющий указатели проще для понимания. TMH>Ты не забыл добавить ИМХО?
Поскольку то, что я пишу — не божественные откровения, всё это ИМХО. А там где я эго явно ставлю — дважды ИМХО. Так вот, это утверждение — просто ИМХО.
SH>>По-моему с этим спорить трудно. TMH>Напиши Страуструпу. Он довольно охотно отвечает на умные письма. И с ним даже можно поспорить. TMH>А вот переспорить — трудновато...
А чего мне с ним спорить? Он со мной согласен.. Я не крутой С++-ник, и Страуструпа читал только "Язык программирования С++" третье издание, на русском языке. Поэтому ссылаюсь на него. Глава 5, параграф 5.8 "Советы". Совет №6: "Старайтесь как можно реже пользоваться простыми (имеется ввиду неконстантыми — SH) ссылками в качестве аргументов функций. См 5.5" В параграфе 5.5 приведены все мои аргументы. Ещё где-то в книжке что-то такое было, но я так сразу не нашёл.
TMH>...Это была преамбуда. Теперь амбула. TMH>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TMH>То ли ссылки, то ли указатели — зависит от многого — legacy code, корпоративный/командный стиль кодирования, личные предпочтения и т.д. Короче — случаи бывают разные и вариантов много. И все они заслуживают уважения. TMH>Лично я более склоняюсь к использованию ссылок — считаю это "хорошим тоном" в C++...
TMH>Теперь по "классам":
[skip]
Согласен.
TMH>Но ИМО нормальный C/C++ программер должен быть знаком и свободно оперировать обоими.
Согласен. Это не слишком навороченные концепции, что бы у профессионального С++ программера тут возникали какие-то проблемы. Речь идёт только о том, что сопровождающему программисту (или тебе самому через месяц-другой) будет проще, если перед изменяемыми аргументами будет стоять &, а перед неизменяемыми — нет. (ИМХО) Так действительно удобнее. То, что этого нет в VB и Pascal — минусы этих языков. В них ещё много чего нет. От всего откажемся?
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Доброго времени суток. АП>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели?
Я соглашусь с Dr_Sh0ck — почти без разницы, но указатели я использую тогда, когда хочу показать, что объект может быть изменен функцией:
f(x); // с x ничего не будет
f(&x); // можно ожидать изменения x
ИМХО так меньше "неожиданностей".
Кроме того, есть еще одна принципиальнвя разница между ссылками и указателями, — ссылка может быть проинициалзирована только один раз. Т.е.:
int i1=1, i2=2;
int &ref1=i1;
ref1=i2; // после этого ссылка не станет ссылаться на i2, но i1 станет равна 2!!!
Здравствуйте Vi2, Вы писали:
Y>>Я читал кажется у Элджера, что он советует использовать ссылки для лаконичности и простоты. А указатели использовать только тогда, когда передаваемый объект может не существовать (т.к. не может быть ссылки на NULL).
Vi2>Ещё как может! Vi2>Т.к. при Type* GetVar(); и возврате валидного NULL для неё в функцию SomeFunc( *GetVar() ) передастся пустая ссылка и без "вполне осознаннах телодвижений — такое по ошибке не сделаешь — в отличие от пустых и некорректных указателей" TepMuHyc. Это может быть и баг VC6.0, но тем не менее ...
Vi2>Так что и ссылками можно наворотить дай бог что.
Наворотить можно много чего. Речь идет о том, что не существует легального способа получить нулевую ссылку в С++. В твоем примере код '*GetVar()' порождает неопределенное поведение, т.к. производит разадресацию нулевого указателя. Таким образом, проверять ссылку на "равенство NULL" внутри такой функции бессмысленно — к этому моменту ошибка в программе уже произошла.
В этом и заключается одно из отличий ссылки от указателя: в случае со ссылкой, проверка на NULL — это задача именно формирующего ссылку кода. А использующий ссылку код такую проверку делать не должен — это не его обязанность. Именно это и имеется в виду в книгах по С++, когда говорится, что ссылка не может быть нулевой.
С указателем ситуация иная — формирующий код имеет полное право сформировать NULL-укзатель, и если использующему коду это важно, то он должен выполнить проверку на NULL самостоятельно.
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>2. Может есть возможность получить ссылку через указатель, не копируя память в другую переменную?
Если указатель валидный и не нулевой, то
Type* var= GetVar();
SomeFunc( *var ) // вобщем-то работает :-)
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Доброго времени суток. АП>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели?
В общем принципиальной разницы нет, но все зависит от того, какого эффекта ты хочешь добиться. Ссылки были введены в С++, в частности, для удобства облегчения реализации перегрузки; дабы не менять семантику указателей в С.
АП>Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит. Так вот набрёл на проблему, когда имеется указатель, а функция принимает ссылку:
АП>
АП>SomeFunc(Type& var)
АП>{
АП> // ...
АП>}
АП>
АП>Type* var= GetVar(); АП>SomeFunc(var) // ???
На счет красивше — может быть, однако очень часто рекомендуют делать так: если ф-ция должна изменить передаваемый ей параметр, то лучше передавать его через указатель — так яснее выглядит на передаваемой стороне.
АП>Что выбрать? АП>1. Заменить параметр функции на указатель, а значит признать, что такая же ситуация может произойти и с другими ссылками.
Уточни.
АП>2. Может есть возможность получить ссылку через указатель, не копируя память в другую переменную?
Ссылка — это псевдоним, значит можно создать ссылку, которая будет псевдонимом объекта, на который указывает указатель. Дело в том, что ссылка не является объектом в понимании С++, т.е. не может быть ссылок нассылку, нельхя получить адрес ссылки; в общем случае память под ссылку вообще может не выделяться — все зависит от конкретного случая, компилятора и т.п.
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>в каких случаях следует предпочесть ссылки,
— Везде где надо передать параметр "по ссылке" — например чтобы вернуть результат выполнения функции
— Везде где желательно избежать передачи "по значению" — например можно передавать объект по значению, но при этом создается временая копия обьекта. Если обьект "большой" — это может быть дорого.
АП>а в каких указатели?
— То же что и выше, но возможен случай что параметр может быть "пустым" — т.е NULL
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Здравствуйте TepMuHyc, Вы писали:
TMH>Здравствуйте Алекс Пронскявичус, Вы писали:
АП>>в каких случаях следует предпочесть ссылки, TMH>- Везде где надо передать параметр "по ссылке" — например чтобы вернуть результат выполнения функции
Жестоко это... , таким образом ты запутаешь человека который твой код будет использовать.
int a = 5;
SomeFunc(a); // Поменяли "a", но мне об этом надо догадаться.
В этом случае надо параметры каждой используемой функции просматривать.
int a = 5;
SomeFunc(&a); // Поменяли a, но я возможность изменения "a" вижу сразу.
Доброго времени суток.
Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели?
Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит. Так вот набрёл на проблему, когда имеется указатель, а функция принимает ссылку:
SomeFunc(Type& var)
{
// ...
}
Type* var= GetVar();
SomeFunc(var) // ???
Что выбрать?
1. Заменить параметр функции на указатель, а значит признать, что такая же ситуация может произойти и с другими ссылками.
2. Может есть возможность получить ссылку через указатель, не копируя память в другую переменную?
Здравствуйте kl, Вы писали:
kl>Просто не стоит использовать неконстантные ссылки, вот и все. К сожалению, при использовании сторонних библиотек это не всегда получается.
Насколько я помню, даже при использовании STL. Не говоря уж про MFC.
Здравствуйте kl, Вы писали:
kl>Здравствуйте yogi, Вы писали:
Y>>Здравствуйте Алекс Пронскявичус, Вы писали:
kl>Просто не стоит использовать неконстантные ссылки, вот и все. К сожалению, при использовании сторонних библиотек это не всегда получается.
Вопрос — чем эмулировать семантику неконстантной ссылки? Только указателем, так что этот совет изоморфен совету "использовать указатель для изменяемых параметров".
Здравствуйте Vladik, Вы писали:
VV>Я соглашусь с Dr_Sh0ck — почти без разницы, но указатели я использую тогда, когда хочу показать, что объект может быть изменен функцией:
V>
V>f(x); // с x ничего не будет
V>f(&x); // можно ожидать изменения x
V>
Здравствуйте yogi, Вы писали:
Y>Здравствуйте Алекс Пронскявичус, Вы писали:
АП>>Доброго времени суток. АП>>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели? АП>>Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит.
Y>Я читал кажется у Элджера, что он советует использовать ссылки для лаконичности и простоты. А указатели использовать только тогда, когда передаваемый объект может не существовать (т.к. не может быть ссылки на NULL). Но я предпочитаю (как еще кто-то в этой теме уже писал)использовать указатели, чтоб подчеркнуть, что объект может быть изменен.
Вопрос о том, где использовать ссылку, а где указатель я для себя решил( следуя советам Круглински, да и судя по вашему ответу и Элджера) уже давно следующим образом:
Если значение нужно изменять, то передаю параметр по ссылке(будь это хоть DWORD).
Если объект изменять не надо и он достаточно громоздкий, то по ссылке на константный объект.
Указатели же использую только в тех функциях, которые манипулируют с паматью.
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Доброго времени суток. АП>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели? АП>Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит. Так вот набрёл на проблему, когда имеется указатель, а функция принимает ссылку:
Здравствуйте yogi, Вы писали:
Y>Я читал кажется у Элджера, что он советует использовать ссылки для лаконичности и простоты. А указатели использовать только тогда, когда передаваемый объект может не существовать (т.к. не может быть ссылки на NULL).
Ещё как может!
Т.к. при Type* GetVar(); и возврате валидного NULL для неё в функцию SomeFunc( *GetVar() ) передастся пустая ссылка и без "вполне осознаннах телодвижений — такое по ошибке не сделаешь — в отличие от пустых и некорректных указателей" TepMuHyc. Это может быть и баг VC6.0, но тем не менее ...
int* GetVar()
{
return NULL;
}
void SomeFunc( int& a )
{
int i;
if( &a == NULL )
i = 1;
else
i = a;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// TODO: Place code here.
SomeFunc( *GetVar() );
return 0;
}
Здравствуйте Edmond, Вы писали:
E>С точки зрения низкоуровневой реализации E>Указатель -- переменная, содержащая адрес... E>Ссылка -- временная переменная..., но
E>Почувствуйте разницу...
Здравствуйте Vi2, Вы писали:
Vi2>Я достаточно часто видел и такое описание функций Vi2>
Vi2>void SomeFunc( int& a = *(int*)NULL );
Vi2>
Vi2>Так что и ссылками можно наворотить дай бог что.
Долго думал. Единственное применение, которое кажется более-менее разумным — получить access violation, если функцию вызвали с параметром по умолчанию Почему бы тогда не убрать вообще умолчание?
Здравствуйте m.a.g., Вы писали:
...>Здравствуйте Vi2, Вы писали:
Vi2>>Я достаточно часто видел и такое описание функций Vi2>>
Vi2>>void SomeFunc( int& a = *(int*)NULL );
Vi2>>
Vi2>>Так что и ссылками можно наворотить дай бог что.
...>Долго думал. Единственное применение, которое кажется более-менее разумным — получить access violation, если функцию вызвали с параметром по умолчанию Почему бы тогда не убрать вообще умолчание?
Почему же, можно проверить корректна ли ссылка (&a!=NULL) и если корректна, то можно ее и использовать.
Другой вопрос зачем это все надо? IMHO, в данном случае использование ссылкм не приносит ни каких удобств по
сравнению с использованием указателей, а только способствует запутыванию кода.
Здравствуйте deviv, Вы писали:
Vi2>>>Я достаточно часто видел и такое описание функций
Vi2>>>void SomeFunc( int& a = *(int*)NULL );
Vi2>>>Так что и ссылками можно наворотить дай бог что.
...>>Долго думал. Единственное применение, которое кажется более-менее разумным — получить access violation, если функцию вызвали с параметром по умолчанию Почему бы тогда не убрать вообще умолчание?
D>Почему же, можно проверить корректна ли ссылка (&a!=NULL) и если корректна, то можно ее и использовать. D>Другой вопрос зачем это все надо? IMHO, в данном случае использование ссылкм не приносит ни каких удобств по D>сравнению с использованием указателей, а только способствует запутыванию кода.
Возможно. На самом деле в реальном примере используются более сложные классы, чем int. Видимо тут (псевдо!)экономия на "->" и ".".
Но я бы не сказал, что это хороший стиль, что ему надо следовать. Даже наоборот так делать не надо. Однако такой код есть, и в достаточно известной фирме.
и может другие есть), что такое выражение *(int*)NULL — неопределённое поведение. То, что код компилится VC6.0 и работает — это просто счастье (короткое?) разработчиков.
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте Edmond, Вы писали:
E>>С точки зрения низкоуровневой реализации E>>Указатель -- переменная, содержащая адрес... E>>Ссылка -- временная переменная..., но
E>>Почувствуйте разницу... Vi2>
E>>Думаю все остальные выводы должны сформироваться автоматически
Vi2>Другой пример SomeFunc( *GetVar() ); при void SomeFunc( int& a ) и int* GetVar() { return NULL; }
Vi2>
Ну и что вы думали этим показать?
Это вообще к делу не относиться.
Это просто пример способа оптимизации кода, при чём то, что я написал?
Ну возвращаемое значение функции в eax. Так что вам собственно не нравиться!!!
Я сделал попытку теор определения: Указатель -- это переменная. Ссылка -- Не обязательно
Ваш пример только подтверждает. После того, как eax попадает в стек, он превращаеться в локальную переменную — значит указатель!!!
Проблемма в локальных переменных... потому что кажеться, что нет различий между указателем и функцией...
Однако разница всё таки громадна. И разработчики C++ знают о ней, и Страуструп знает, иначе никто никогда б не вводил их в C!
Но эту разницу нельзя увидить в коде. Она есть в способе создания кода компилятором.
Да это теории, теории, и теории.
Я просто попытался привести лёгкий и наглядный пример, чтобы у программиста сразу сформировалось впечатление.
Здравствуйте Vi2, Вы писали:
Vi2>>>>Я достаточно часто видел и такое описание функций Vi2>
Vi2>>>>void SomeFunc( int& a = *(int*)NULL );
Vi2>
Vi2>Но я бы не сказал, что это хороший стиль, что ему надо следовать. Даже наоборот так делать не надо. Однако такой код есть, и в достаточно известной фирме.
Vi2>Где-то в прошлых топиках было (http://www.rsdn.ru/forum/message.asp?mid=49650&only
и может другие есть), что такое выражение *(int*)NULL — неопределённое поведение.
"Неопределенное поведение" — термин языка С++. Означает, что стандарт языка не определяет, как именно должен вести себя компилятор при встрече с такими моментами, или, вернее, как должна себя вести программа с таким кодом. Но! Тот код, о котором ты говоришь, написан чисто для этого компилятора, чье поведение досконально известно.
Таким образом, с точки зрения чистого С++ этот код опасен, т.е. слабо переносим (но все-таки переносим в пределах как-минимум одного компилятора во всех его версиях), но высказывание Vi2>То, что код компилится VC6.0 и работает — это просто счастье (короткое?) разработчиков.
верно только для тех, кто не знает, что делает.
Этот код — Microsoft specific, короче.
Все, что написано Microsoft и для Microsoft (MFC, STL), написано для конкретного компилятора, и может опираться на его особенности реализации. Таким образом, код становится более платформно-зависимым, что совсем не значит, что плохим. Давно известно, что чем более общо сделана некоторая вещь, тем труднее ее использовать (примеров масса: от фукнкции qsort до MSWord).
Здравствуйте Kaa, Вы писали:
Kaa>Таким образом, с точки зрения чистого С++ этот код опасен, т.е. слабо переносим (но все-таки переносим в пределах как-минимум одного компилятора во всех его версиях), но высказывание
А откуда взялось "во всех его версиях"?
Best regards,
Андрей Тарасевич
Re[8]: Псевдо-экономия
От:
Аноним
Дата:
22.07.02 17:49
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>А откуда взялось "во всех его версиях"?
Z™>int a = 5;
Z™>SomeFunc(a); // Поменяли "a", но мне об этом надо догадаться.
Z™>В этом случае надо параметры каждой используемой функции просматривать.
Z™>int a = 5;
Z™>SomeFunc(&a); // Поменяли a, но я возможность изменения "a" вижу сразу.
Я же использую оба варианта в зависимости от того, можно ли по имени SomeFunc определить, изменяет ли она параметр или нет. Если с первого взгляда кажется, что она не изменяет параметр, а на самом деле делает так, то лучше передать указатель. Если смысл ф-ии в изменении своего аргумента, то ради красивости можно передать и ссылку.
Когда есть возможность написать x = f(x), именно так и стоит делать. К сожалению так бывает не всегда.
На самом деле, все зависит от стиля, который ты выбрал. Если твой взгляд не царапает обилие укзателей, почему бы и нет.
Здравствуйте TepMuHyc, Вы писали:
TMH>Теперь другой пример: SomeFunc(5); И что же нам скажет компилятор? TMH>Я думаю выдаст трезвую и взвешенную оценку умственных способностей программиста.
В обоих случаях скажет, что не может привести один тип к другому.
TMH>2) Программист не желает читать документацию. В этом случае его умственные TMH>способности а также обстоятельства его зачатия, рождения и воспитания будут TMH>подробно рассмотрены в курилке другими программерами. Или же работодателем...
3) Документация отсутствует или она очень плоха.
Код, применяющий указатели проще для понимания. По-моему с этим спорить трудно. А если тебе по каким-то причинам не нравятся указатели, можешь переходить на Джаву! :-)
Здравствуйте Алекс Пронскявичус, Вы писали:
АП>Доброго времени суток. АП>Вот вопросец небольшой, в каких случаях следует предпочесть ссылки, а в каких указатели? АП>Я раньше где-то читал, что, где возможно, лучше использовать ссылки — красивше выглядит. Так вот набрёл на проблему, когда имеется указатель, а функция принимает ссылку:
АП>
АП>SomeFunc(Type& var)
АП>{
АП> // ...
АП>}
АП>
АП>Type* var= GetVar(); АП>SomeFunc(var) // ???
АП>Что выбрать? АП>1. Заменить параметр функции на указатель, а значит признать, что такая же ситуация может произойти и с другими ссылками. АП>2. Может есть возможность получить ссылку через указатель, не копируя память в другую переменную?
// В данном случае наиболее подходящий вариант вызвать ф-цию след. образом
SomeFunc (*var);
// В этом случае в качестве параметра будет передаваться по ссылке не указатель а
// обьект на который он указывает
Z™>>int a = 5;
Z™>>SomeFunc(a); // Поменяли "a", но мне об этом надо догадаться. TMH>Теперь другой пример: SomeFunc(5); И что же нам скажет компилятор? TMH>Я думаю выдаст трезвую и взвешенную оценку умственных способностей программиста.
Что то ты напутал... Он выдаст "cannot convert parameter 1 from 'int' to 'int*' и ничего больше. А это означает что ты уже обсуждаешь другую функцию (которую еще надо написать, если ты просто значение передаешь).
Z™>>В этом случае надо параметры каждой используемой функции просматривать. TMH>Их в любом случае просматривать надо перед тем как вызов оной функции писать. TMH>Хотя бы для того чтобы иметь представление что данная функция делает.
Я пишу не про написание вызова функции. Я пишу про сопровождение написанного кем то кода. Просматривая сотни строк кода, постоянное рытье в документации сильно утомляет, надо ведь каждую функцию подозревать в изменении переменных, если где то используется возврат по ссылке. Зачастую самые "умные" куски кода вообще не документируются.
Не надо смешивать сложность с запутанностью , надо писать так, что бы код поменьше напрягал мозги впоследствии.
TMH>Теперь тот же пример немного по-другому: SomeFunc(0); — тоже вполне TMH>корректно, а последствия, думаю, очевидны.
Неужели трудно хотя бы в дебаг версии проверять параметры функции ?
Мне встречались люди которые оправдывали свою лень и нежелание хотя бы вставлять ASSERTы, тем, что неправильное значение в функцию никогда не передается.
Книгу Ален И. Голуба. "Правила программирования" всем рекомендую, там все разжевано.
Зачастую что то (кого то) обсуждают в курилках владея искаженной или неполной информацией.
Здравствуйте Zilog™, Вы писали:
Z>>>В этом случае надо параметры каждой используемой функции просматривать. TMH>>Их в любом случае просматривать надо перед тем как вызов оной функции писать.
Z™>Я пишу не про написание вызова функции. Я пишу про сопровождение написанного кем то кода.
Хрен редьки не слаще. Для того чтобы код сопровождать ты его должен ЗНАТЬ. В идеале — знать что делает КАЖДАЯ
функция. А следовательно просмотреть доку или код данной функции.
Z>Просматривая сотни строк кода, постоянное рытье в документации сильно утомляет
Позволь спросить, а за что тебе зарплату платят? За твои красивые глаза? Или за то что ты код сопровождаешь? Если же тебя так утомляет умственная нагрузка лучше переведись в животноводы...
Z>надо ведь каждую функцию подозревать в изменении переменных, если где то используется возврат по ссылке.
Сразу впоминается анекдот: "Слониху изнасиловали — всех подозревают"... Если уж подозреваешь не сочти за труд — поставь на этом вызове брекпойнт... или почитай по функции доку.
Z>Зачастую самые "умные" куски кода вообще не документируются.
Преблема ВАШЕЙ корпоративной культуры — это еще не глобальная проблема.
TMH>>Теперь тот же пример немного по-другому: SomeFunc(0); — тоже вполне TMH>>корректно, а последствия, думаю, очевидны. Z>Неужели трудно хотя бы в дебаг версии проверять параметры функции ?
Только вот заметь, что если аргумент — ссылка, то этого не надо делать ВООБЩЕ.
Z>Зачастую что то (кого то) обсуждают в курилках владея искаженной или неполной информацией.
А обсуждают-то своего товарища, а потом когда заваривается новый проект и набирается команда никто его в этой новой команде видеть не хочет... И это не фантазии — сам знаю одного такого — у него зарплата не меняется со дня поступления на работу — вот уже 4 года...
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Kaa>Все, что написано Microsoft и для Microsoft (MFC, STL), написано для конкретного компилятора, и может опираться на его особенности реализации. Таким образом, код становится более платформно-зависимым, что совсем не значит, что плохим. Давно известно, что чем более общо сделана некоторая вещь, тем труднее ее использовать (примеров масса: от фукнкции qsort до MSWord).
Не надо путать общность алгоритма и независимость от особенностей реализации. Сама Microsoft категорически НЕ рекомендует полагаться на особенности реализации и НЕ гарантирует их переход от версии к версии.
Здравствуйте Mink, Вы писали:
M>Не надо путать общность алгоритма и независимость от особенностей реализации. Сама Microsoft категорически НЕ рекомендует полагаться на особенности реализации и НЕ гарантирует их переход от версии к версии.
Я ничего не путаю. Я сказал, что код этот написан с уклоном, и народ, который его написал, точно знал, что и для чего он это делал. Перечитай.
Здравствуйте TepMuHyc, Вы писали:
Z>>>>В этом случае надо параметры каждой используемой функции просматривать. TMH>>>Их в любом случае просматривать надо перед тем как вызов оной функции писать.
Z™>>Я пишу не про написание вызова функции. Я пишу про сопровождение написанного кем то кода. TMH>Хрен редьки не слаще. Для того чтобы код сопровождать ты его должен ЗНАТЬ. В идеале — знать что делает КАЖДАЯ TMH>функция. А следовательно просмотреть доку или код данной функции.
В большом проекте знать ВСЕ ВО ВСЕХ ДЕТАЛЯХ просто нереально.
Z>>Просматривая сотни строк кода, постоянное рытье в документации сильно утомляет TMH>Позволь спросить, а за что тебе зарплату платят? За твои красивые глаза? Или за то что ты код сопровождаешь? Если же тебя так утомляет умственная нагрузка лучше переведись в животноводы...
Позволь спросить, а за что тебе зарплату платят ? За то что бы ты писал код который впоследствии (мало ли, может работу поменяешь) будет очень дорогим в сопровождении ?
TMH> Z>>надо ведь каждую функцию подозревать в изменении переменных, если где то используется возврат по ссылке. TMH>Сразу впоминается анекдот: "Слониху изнасиловали — всех подозревают"... Если уж подозреваешь не сочти за труд — Я нехочу ничего подозревать, я просто хочу что бы код был максимально прозрачным. Код который понятен без документации (это не значит что документации быть не должно) намного лучше кода в котором и с документацией разобраться тяжело.
TMH> поставь на этом вызове брекпойнт... или почитай по функции доку.
Хехе, если вызов этой функции (ты еще не знаешь какой) за n строк до места где проявились следствия проблемы ? Или ты предлагаешь в пошаговом режиме всю программу отлаживать ?
Z>>Зачастую самые "умные" куски кода вообще не документируются. TMH>Преблема ВАШЕЙ корпоративной культуры — это еще не глобальная проблема.
У нас такие проблемы возникают после соприкосновения с ВАШЕЙ корпоративной культурой, одно радует что этих соприкосновений все меньше и меньше, помирают такие культуры.
TMH>>>Теперь тот же пример немного по-другому: SomeFunc(0); — тоже вполне TMH>>>корректно, а последствия, думаю, очевидны. Z>>Неужели трудно хотя бы в дебаг версии проверять параметры функции ? TMH>Только вот заметь, что если аргумент — ссылка, то этого не надо делать ВООБЩЕ.
Сомнительная экономия.
Код должен быть прозрачным, если тебя действительно интересует, почему такой подход содержит проблемы, а мои слова у тебя особого доверия не вызывают, прочитай книжку о которой я выше писал.
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте Zilog™ и TepMuHyc, вы писали:
Vi2>Я думаю, что можно обсуждать вопросы без проставления нулей, тем более что исходный ответ TepMuHyc не заслуживал такой оценки изначально — он никому не грубил, не хамил, не навязывал свою точку зрения и т.п. Если уж, уважаемый Zilog™, имеете претензии лично к TepMuHyc, то перейдите на личную переписку и выскажите там все.
Я ни имею никаких личных претензий к TepMuHyc, просто в этом вопросе я с ним жестко не согласен, оценил соответственно.
Vi2>То, что вы начали обсуждать — это дело вкуса, принятых в кампании правил и т.п., и тут уж каждый будет считать своё решение единственно правильным.
Просто я описал какие последствия это влечет, а также сказать что бед это принесет гораздо больше чем сулит выгод.
Здравствуйте Zilog™ и TepMuHyc, Вы писали:
Z>Я ни имею никаких личных претензий к TepMuHyc, просто в этом вопросе я с ним жестко не согласен, оценил соответственно.
Не хотел бы втягиваться в вашу дискуссию, но всё-таки придётся не надолго.
Я не выступаю ни против ваших оценок, ни против вашей полемики — это ваше дело, хоть всё пространство сервера заполняйте. (Хотя его и жалко).
Просто я хотел призвать к голосу разума: в области чувств, вкуса и т.п. споры бесполезны — каждый останется при своём при любом раскладе. Поэтому результатом всей "дискуссии", очевидно, будет финал: Ты-чайник!Сам-такой!, и недовольство вашим оппонентом и т.д.
Однако, если вы хотите и дальше встречаться в форуме, то такие споры приводят к тому, что впоследствии именно ваш сегодняшний оппонент смог бы решить вашу завтрашнюю проблему, но он не сделает этого в силу личной обиды на вас.
Поэтому я призываю — не прибегать к таким дискуссиям и останавливать других, новичков, в форуме.
Если есть крутые ошибки — доказывайте неправоту! Потому что это доказуемо, а то, что нравится — не нравится, пусть останется за бортом вашего внимания или без комментариев Ты-чайник!.
Здравствуйте Vi2, Вы писали:
Vi2>Если есть крутые ошибки — доказывайте неправоту! Потому что это доказуемо, а то, что нравится — не нравится, пусть останется за бортом вашего внимания или без комментариев Ты-чайник!.
Какие еще надо даказательства ? Секундомер ?
SomeFunc(a, b, c); // Смотрим документацию, если нет то заголовки.
SomeFunc(&a, b, &c); // Не надо смотреть документацию, заголовки, и так все понятно.
Z™>Здравствуйте Vi2, Вы писали:
Vi2>>Если есть крутые ошибки — доказывайте неправоту! Потому что это доказуемо, а то, что нравится — не нравится, пусть останется за бортом вашего внимания или без комментариев Ты-чайник!.
Z™>Какие еще надо даказательства ? Секундомер ?
Доказательства.
Z™>SomeFunc(a, b, c); // Смотрим документацию, если нет то заголовки.
Z™>SomeFunc(&a, b, &c); // Не надо смотреть документацию, заголовки, и так все понятно.