| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Вопрос из книги Страуструпа |
| Автор: shuttle 17.6.2009, 12:13 | ||
Как понимать следующее описание? Где оно может пригодиться?
Что то не могу ссобразить. |
| Автор: xvr 17.6.2009, 12:30 | ||
Референс на функцию, принимающую 2 параметра (оба int) и возвращающую int.
|
| Автор: shuttle 17.6.2009, 12:34 |
| это Страуструп написал в книге "Язык программирования С++". Очень кстати толковая книга. |
| Автор: kemiisto 17.6.2009, 12:37 |
Это видно потому, что Вы спрашиваете. |
| Автор: zim22 17.6.2009, 12:51 | ||
у меня оно вообще не компилится. http://codepad.org/t9HY5Sqr может быть имелся ввиду указетель на функцию?
какая страница? какое издание книги? |
| Автор: shuttle 17.6.2009, 13:09 |
| Бьерн Страуструп. Язык программирования С++ Второе дополненное издание Языки программирования / С++ там еще на обложке морская волна. страница 120. упражнение 2. |
| Автор: zim22 17.6.2009, 13:15 |
у меня другая книжка "Специальное издание" isbn 5-7989-0223-4 *** у меня на стр.120 вообще нет упражнений. |
| Автор: shuttle 17.6.2009, 13:29 | ||||
| Все разобрался, сравнил с "Язык программирования С++ специальное издание", у меня точно опечатка должно быть так
а не
В "Язык программирования С++ специальное издание" это 206 страница. |
| Автор: zim22 17.6.2009, 13:38 | ||||
для чего это может пригодиться... для этого:
*** плохой пример я привёл... исправляюсь
|
| Автор: andrew_121 17.6.2009, 13:45 |
| А в чем разница между указателем на функцию и ссылкой? |
| Автор: mes 17.6.2009, 13:47 |
в том, что ссылка должна быть изначально инициализирована. |
| Автор: zim22 17.6.2009, 13:47 |
наверное в том же, в чём разница между передачей аргументов по указателю и ссылке |
| Автор: andrew_121 17.6.2009, 13:50 | ||
Походу, это единственный смысл.
Это разные случаи. |
| Автор: mes 17.6.2009, 14:37 | ||
чего то захотелось вспомнить молодость и написать простой калькулятор, заодно демонстрация по теме :
|
| Автор: zim22 17.6.2009, 15:11 | ||
видать в молодости вы тоже ошибки делали попробуйте операцию умножить сделать. *** в класс добавил конструктор. почему компилятор не ругается? ведь ссылка (op_t operation) должна быть инициализирована. иначе при её вызове получим runtime error.
*** в GCC ругается! а вот Студия молчит. |
| Автор: azesmcar 17.6.2009, 15:32 |
очередная ошибка студии... |
| Автор: mes 17.6.2009, 15:37 | ||
ага .. как же без них.. else лишнее.. по запарке добавил |
| Автор: azesmcar 17.6.2009, 15:37 | ||||
это работает..ну как сказать работает Добавлено через 1 минуту и 14 секунд если заменить на int& - орет нечеловеческим голосом, а вот с функциями - молчит как партизан |
| Автор: andrew_121 17.6.2009, 16:08 |
| azesmcar, Какой компилятор? |
| Автор: azesmcar 17.6.2009, 16:09 |
VS2008 Professional |
| Автор: andrew_121 17.6.2009, 22:28 |
| Я так и думал. Жаль не могу сам проверить сей факт. |
| Автор: zim22 18.6.2009, 18:18 | ||||
| думаю сюда вопрос напишу, т.к. это вопрос и он из книги Страуструпа *** В книге написано, что:
И приводится пример кода:
так вот, где "правильно" написано - оно не правильно. Линкер ругается на unresolved external symbol или Страуструп имел ввиду правильность с точки зрения компилятора, а не линкера? |
| Автор: mes 18.6.2009, 18:24 | ||||
Имел ввиду что где то в дальнейшем тело функции будет написано. Но не написал, так как само тело не относится к обсуждаемому вопросу .
никаких ошибок связанных с этой цитатой в коде нет |
| Автор: EvilsInterrupt 11.10.2009, 00:50 | ||||||||
| У меня есть два вопроса относительно того, что поясняет в своей книге Страуструп. Вопрос №1: В 6.2 "Обзор операторов" на странице 163, он приводит код:
и ниже текст:
Не совсем понимаю, как может то что справа быть lvalue-ем ? Ведь lvalue это то куда присваивают значение?! Вопрос №2: Рядышком, на следующей 164 страничке в Главе 6. Выражения и инструкции. Есть код:
и слова:
Не совсем понимаю эту "неопределенность" . возникнуть чтото отличное от v[1] = 1; ? Хоть один компиллер назовите, который генерит такую вот неопределеность ? |
| Автор: GoldFinch 11.10.2009, 00:58 | ||||
EvilsInterrupt, может произойти
Добавлено через 1 минуту и 16 секунд EvilsInterrupt, lvalue - Это то что может быть слева. это не запрещает ему при это быть и rvalue |
| Автор: EvilsInterrupt 11.10.2009, 01:09 |
| GoldFinch, я привык видеть конкретный код! Назови плиз хоть один компиллер, который генерит подобное ? |
| Автор: mes 11.10.2009, 01:34 | ||||||
например gcc в основном так и поступает, в отличии от студии которая (по крайней мере при стандартных настройках) более дружественная к пользователю, и старается предугать как поступить.
|
| Автор: zim22 11.10.2009, 09:06 | ||||
очень просто определить, является ли объект lvalue или rvalue достаточно попробовать взять его адрес
|
| Автор: EvilsInterrupt 11.10.2009, 13:29 | ||||||
| Ладно, случай с компиллером оставлю до завтра, когда самплов на генерю наработе. А вот вопрос с lvalue хочется все-таки до понять. Порывшись в поисковике увидел: http://athena.vvsu.ru/carina/oop/link/cpps/ref_3.shtml.htm сказано, также как считаю и я:
есть
это можно раскрыть в:
тута вижу только p ,как lvalue . Потому что &x, &y стоят справа! Поэтому мне и не понятно, почему это Страуструп объект стоящий справа, а не слева называет lvalue ?! P.S.: Пока ктото напишет мне могу взорваться от непонимания и потому пока почитаю http://www.rsdn.ru/article/cpp/lvalue.xml ))) |
| Автор: mes 11.10.2009, 13:55 | ||
lvalue не обязательно должен стоять физически слева. например int а, b; a = b; // а и b lvalue несмотря на то что одно стоит слева другое справа. если точнее, то в данном примере справа в роли rvalue выступает lvalue b; подобно как например в русском языке имя прилагательное может переходить в разряд имен существительных : больной (прил) человек и больной (сущ). так и в программировании выражение одной сути может исполнять роль другой. |
| Автор: EvilsInterrupt 11.10.2009, 14:11 | ||
| Кажется начал понимать, прошу проверить ход мыслей до вывода ;) Ввиду того что с любым выражением как-то должно связано либо адрес со значением по этому адресу, либо просто значение. То хочется различать просто значение от значения по адресу, поэтому и обозначили значение лежащее по адресу как lvalue. Наскоко понял из статьи что у меня в P.S.: из прошлого поста, то первоначально это и обозначало объект стоящий слева от присваивания, а сейчас компиллеры стали круче и потому уже не актуально ) Из той же статьи, что в P.S.:
не понятно, почему последнее i++ написано rvalue ? Попробую представить как i += 1 и вроде как понятно, что такое не может быть lvalue , т.е. в такое мы не можем кинуть значение, но почему тогда ++i является lvalue ? ведь посути это можно писать как result = (i+=1,i); в такое тоже сложно представить чтобы чтото писать ?! ;) |
| Автор: mes 11.10.2009, 14:19 | ||
потому что возвращают разное :
|
| Автор: mes 11.10.2009, 14:58 | ||
при чем тут мощность компиляторов я не понял |
| Автор: EvilsInterrupt 11.10.2009, 15:18 |
| mes, ну к тому, что раньше lvalue применялось исключительно к объектам слева от присваивания и только им ;) Так по крайней мере баит дядя Бьярни ) |
| Автор: mes 11.10.2009, 15:44 | ||
это с мощностью компилятора никак не связано... |
| Автор: xvr 11.10.2009, 19:59 |
| lvalue это не то, что СТОИТ слева от оператора присваивания, а то, что МОЖЕТ стоять слева, т.е. то, чему можно присвоить. Это так же означает, что у этих объектов можно взять адрес, т.е. они представляют некую сущность, существующую не только в процессе вычисления выражения. Тут int * p = &(x>y ? x : y); x и y представляют собой такие сущности (это переменные), у них можно взять адрес и им можно присвоить. Т.е. результат всего оператора ? будет являться lvalue, и от него можно взять адрес. Если же мы рассмотрим такое выражение int * p = &(x>y ? x+y : y);, то x+y не является lvalue, т.к. это значение существует только внутри выражения, и недоступно как отдельный объект. У него нет адреса, который можно было бы взять, и оператор ? не будет lvalue. Заметим, что если бы x и y были объектами для которых был бы перегружен оператор +, как возвращающий lvalue (например ссылку), то оператор ? снова стал бы lvalue (за что С++ иногда и критикуют |
| Автор: stat007 11.10.2009, 21:53 |
| shuttle, Лучше читай Страуструпа - 3-е издание... Там всё более понятнее... |
| Автор: bsa 12.10.2009, 10:21 |
| Лучше Страуструпа вообще не читать, пока не станешь разбираться в С++. Сначала надо изучить С++, затем прочитать Мейерса и Александреску, а потом уже можно и за "Страуса" браться... |
| Автор: zim22 12.10.2009, 10:36 | ||
bsa, не соглашусь. я сейчас читаю Страуструпа - ничего там сложного нет. главное - вдумчиво читать (Страуструп - это моя вторая книга по С++. Первую прочитал Стенли Липпман "Язык программирования С++. Вводный курс. 4 издание") Александреску гораздо сложней для понимания. |
| Автор: bsa 12.10.2009, 10:58 |
| zim22, это не мое мнение. Но знающие люди утверждают, что страус может сбить с пути истинного неокрепший ум новичка. Поэтому прежде чем его читать, нужно знать, что есть хорошо, а что плохо. |
| Автор: zim22 15.10.2009, 19:25 | ||||||||
| Сегодня натолкнулся на один абзац текста, правдивость которого поставил под сомнения. Действительно ли в нижеприведённом коде преобразования типов не разрешаются?
*** zim22: Но если немножко изменить функции, то будет вызвано преобразование из Index в int для первого аргумента функции.
|
| Автор: bsa 18.10.2009, 18:43 |
| zim22, вот тебе и ответ, почему новичкам читать его не следует. |
| Автор: zim22 19.10.2009, 16:41 |
| прочитав ещё пару страниц - снова споткнулся на непонятную мне ошибку. отложу Страуструпа до лучших времён |
| Автор: EvilsInterrupt 11.12.2009, 21:44 | ||
| Возник вопрос, прошу пояснить ;) Есть код из книги Страуструпа:
Мне непонятно что именно инкрементируется ? Предположения: 1) Тот int что был указан в создании гистограммы и строку поместили в мап и ассоциированный с нею инт инкрементируется ? 2) Каждому объекту не явно задается какой-то инт и его можно инкрементировать ? попутный доп. вопрос: при создании в мапе создается исключительно один инт и одна стринг, или в довесок еще доп. инт, так сказать служебный куда помещается хэш или еще чтото в этом роде ? ЗЫ: сорри, в сорцах заблудился и пока знаний маловато чтобы подобного рода вещи узнавать ) |
| Автор: Abyx 11.12.2009, 21:54 | ||
| EvilsInterrupt, очевидно инкрементируется int который в карте какбэ эта карта состоит из int и фактически код представляет собой
|
| Автор: EvilsInterrupt 11.12.2009, 21:55 |
| Abyx, Спасибо ) А доп. вопрос ? ;) |
| Автор: Abyx 11.12.2009, 21:57 | ||
в map хешей нет, там бинарный поиск по упорядоченным ключам т.е. если ключи - string, пары сортируются в алфавитном порядке |
| Автор: EvilsInterrupt 11.12.2009, 21:57 |
| Abyx, Огромное спасибо. |
| Автор: Abyx 11.12.2009, 21:59 |
| для хешей надо другой контейнер, boost::unordered_map, он же std::tr1::unordered_map http://www.boost.org/doc/libs/1_41_0/doc/html/unordered.html |
| Автор: wedens 11.12.2009, 22:30 | ||
| дабы не создавать новую тему, спрошу здесь. как как калькулятор из книги находит имя переменной и возвращает её значение?
здесь я так понимаю в v возвращается значение, если в map существует запись string_value, а если не существует, то создается. но как тогда в эту запись приписывается double значение? |
| Автор: xvr 11.12.2009, 22:56 | ||||||||
Рассмотрим, что тут написано (вот это histogram[s]++;):
Затем инкрементируется значение по возвращенной ссылке.
|
| Автор: Леопольд 13.12.2009, 21:10 | ||
Помню тоже долго разбирался в нём. Я считаю что это пример отвратителен с точки зрения поддержки и расширения. Возможно я ошибаюсь, не спец в проектировании, но на мой взгляд, код безоговорочно должен быть простым для понимания, частенько в этом помогают комментарии, но самое главное, надо реализовать алгоритм, понятный для человека - дерево синтаксического разбора разбивает выражение по приоритетам, потом всё выражение вычисляется и т.д. А у Страуструпа, насколько помню, три функции рекурсивно вызывают друг друга в зависимости от нескольких ифоф, и создают приличную "мешанину" в стеке вызовов, которую тяжело проследить. При этом всё жестко завязано с парсером, брр... У него изначально функциональность разделена на части неправильно. Жаль что он не написал перед началом примера Внимание! Плохой стиль. Ни в коем случае не пытайтесь повторить! |
| Автор: EvilsInterrupt 13.12.2009, 23:33 |
| Леопольд, Буквально месяца 2-3 назад читал код калькулятора Страуструпа и понял его буквально за 30 мин. Сейчас смотрю и думаю чего там сложного-то ? Что собственно произошло за это время? По своим антивирусным задачам, дома(если шеф увидит Думаю Бьярн, как и многие люди поступил как обычный человек: "Мне же понятно, вот же есть грамматика, вот есть код. Возьму элементарнейший калькулятор, каких еще поискать", но он забывает, что по его книге могут учиться совсем ньюбы! А возможно и не забывает, а сделал допущение что читают уже серьезные люди когда-то программившие на си и теперь изучающие плюсы. Мое личное мнение по поводу книги, Страуструп предположил, что язык вышел излишне сложным и поэтому пишет даже в начале : "Если вы чтото не поняли, не переживайте и идите дальше. В дальнейших главах будем говорить более детально". Также думаю, что он писал книгу прежде всего для программистов на языке Си. Это учитывая тот факт, когда она появилась впервые и какую цель он преследовал создавая язык, какие сложности вставали до его языка. А дальше просто ее саппортил ;) Вот и вышло, старые грабли, получили новую жизнь ! Вывод: Читать, читать, но читать много проходно! Как компиллер проходит по сорцу! Сначала токены, потом лексемы, потом грамматика и т.д. и т.п. ;) |
| Автор: EvilsInterrupt 14.12.2009, 08:58 |
| Читаю про enum-ы ;) вот, что пишет: "Диапазон значений перечисления определяется след. образом. Пусть n-максимальное возможное значение элемента перечисления . Пусть m-такое минимальное целое, что 2^m-1 больше или равно n. Тогда верхняя граница диапазона равна 2^m-1. Если наименьший элемент имеет неотрицательное значение, нижняя граница диапазона равняется нулю. Если наименьшее значение отрицательно, нижней границей диапазона является наименьшая ближайлая отрицательная степень двойки плюс 1. Таким образом, диапазон определяется минимальным количеством бит требуемым для представления значений всех элементов перечисления" из этого следует, что автор сделал допущение в сторону мало-мальски математематически подкованного читателя! |
| Автор: Леопольд 14.12.2009, 13:35 | ||
Думаю, мне бы сечас тоже особого труда не составило, потому что я сейчас работаю на языке, где goto использутеся буквально через каждые 10 строк кода. Точнее поддерживаю этот бред. А так как книга Страуструпа была у меня второй, после Подбельского и мышление ещё не выработалось, я разбирался в "калькуляторе" около дня. |
| Автор: EvilsInterrupt 14.12.2009, 14:27 |
| Леопольд, готу рулит! ;))) я сам ща в таком коде плаваю из-за рабочей задачи поставленной партией ;) мало того что это гоуту, так еще коду 10 лет и писало его столько же же чел, каждый возвращался в разные промежутки временного отрезка год, два . А люди как правило за годы "умнеют" и написание кода тоже меняется. Это не есть хорошу(первоначальный вариант этого сообщения было грубее, сорри) |
| Автор: Леопольд 14.12.2009, 15:14 |
Хех, "моему" коду не менее 20 лет. И писало его человек надцать, если не больше. Вся система состоит из 1000 - 1500 файлов по 15000-70000 строк кода (вместе с комментами). Никто её не знает целиком, только небольшую её часть. Это добро, примерно на 70% задокументированно, но качество документации хромает на все конечности |
| Автор: EvilsInterrupt 14.12.2009, 20:56 |
| Леопольд, Будут мысли хорошего и эффективного рефакторинга кода с goto пиши! ;) Только плиз в виде отдельной темы, все равно понадобиться. Хотя бы нам двоим хранить мысли по войне с готу ) |
| Автор: bsa 14.12.2009, 21:24 | ||
1. разделение на функции (return лучше, чем goto) 2. выделение части кода в цикл do { }while (false); 3. исключения, но это в редких случаях (когда речь идет об обработке редких ошибок). |
| Автор: EvilsInterrupt 14.12.2009, 21:39 |
| bsa, бросание исключений не допустимо! код нужен максимально быстрым! по поводу return и создание циклов согласен. Но я пока некоторые куски кода выделяю в новые методы и их дергаю, а их уж мне проще править ) |
| Автор: djamshud 14.12.2009, 21:42 |
| EvilsInterrupt, а зачем рефакторить goto, если оно к месту? Обрабатывать ошибки с ним можно красиво и понятно. Выходить из множества циклов тоже - единственное вменяемое решение. Если же речь идет про код, сплошь утыканный такого рода переходами, то и рефакторинг не поможет - если не нравится, нужно просто переписывать плохие места. >1. разделение на функции (return лучше, чем goto) Если только goto изначально используется в качестве вызова части кода, аля функции. Но это уже клиника, и разработчик нуждается в лоботомии. >2. выделение части кода в цикл do { }while (false); Шикарнейший костыль. Что люди только не делают, лишь бы не использовать правильный гоуту. |
| Автор: bsa 15.12.2009, 11:41 | ||||||
Ну не скажи:
Угу, а кто спорит? Модератор: Давайте вернёмся к теме обсуждения. |
| Автор: Леопольд 15.12.2009, 11:48 | ||
Не, не будут. Я не на плюсах работаю :( Так называемый PLEX. Хуж того. На PLEX'е я пишу тлько для того, что-бы этот дело, вручную перегнать в ASA - местный ассемблер. |