C>Нет. Ссылки, особенно константные ссылки, — это способ самодокументации кода. Если метод принимает константную ссылку — вызывающий может быть уверен, что метод не будет менять объект по этой ссылке (в разумном коде, естественно).
Понимаете, ядерные разработчики не только ядро знают зачастую я знаю, что const — это хорошо.
Но я не виноват, что Катлер с Луковским его невзлюбили и сделали все ядерные (и половину Win32шных) АПИ без него (кажется, Линус его тоже не любит). В итоге, чтобы не морочиться с кастами, приходится это "отсутствие const" волочь за собой везде и всюду.
C>Лучше. Константные ссылки — это по сути оптимизация передачи по значению. В частности, очень частно это делается при передаче временных объектов. Если же брать на них указатель — то мы не можем знать сохранит ли вызываемый код где-то у себя. В случае со ссылками мы знаем, что вызываемый код не будет сохранять переданое ему значение (ну если его не идиоты пишут, конечно).
Вот про идиотов хорошая оговорка. Идиоты могут передать ссылку в конструктор какого-то класса и позвать его через new.
Можно в комментарии к функции оговорить время жизни объекта, и имеет ли право функция сохранять данный указатель где-то.
Pzz>Это плохая оптимизация — у нее слишком много тонких эффектов. Если что-то не может быть сделано прозрачно (а дешевая передача объектов в языке типа Си/C++ не может быть сделана прозрачно, в силу очень открытого интерфейса к реальной памяти машины), то лучше не делать этого вовсе.
Как хорошо, что Си не дает передавать структуры by value... и временных объектов не плодит...
Здравствуйте, Maxim S. Shatskih, Вы писали:
C>>Нет. Ссылки, особенно константные ссылки, — это способ самодокументации кода. Если метод принимает константную ссылку — вызывающий может быть уверен, что метод не будет менять объект по этой ссылке (в разумном коде, естественно).
MSS>Не согласен. Чем плохо const T* ?
Здравствуйте, Maxim S. Shatskih, Вы писали:
E>>Как человек, которому на C++ довелось посчитать математику (в том числе и с матрицами комплексных чисел в 99-2000-й годах)
MSS>Вот конкретно матрицы и есть тот редкий случай, когда operator — по делу.
Ну с матрицами вопрос спорный. operator[] для разных хитрых матриц -- да, по делу. А вот разные operator+ или operator* -- тут можно и к expression templates приплыть.
А вот примеры с std::complex или какими-то другими типами, выдающими себя за числа -- это как раз показательно.
E>>и сделать несколько систем сериализации/десериализации данных
MSS>Зачем overloading для этого? << как запись куда-то — это неинтуитивно. Кроме того, операция 2местная, а если туда надо format spec передать?
format spec -- это к сериализации/десериализации не относится, особенно к двоичной.
MSS>Почему не cout.output(i).output(j)?
Потому, что output -- это метод какого-то класса. И в C++ у меня нет возможности расширять чужой класс перегруженными методами для своих типов. Если кто-то сделает, например:
class asn_1_per_stream_t
{
public :
void
output( const asn_1_object_t & what );
...
};
То это значит, что кроме asn_1_object_t я в поток поместить не смогу. Что разработчик класса asn_1_per_stream_t придумал для output -- только то и можно использовать.
А в случае с перегрузкой операторов можно сделать сдвиг в asn_1_per_stream_t любых объектов, даже тех, которые от asn_1_object_t не производны, но могут через них выражаться. Например, объект ACE_Date_Time.
И в случае с перегрузкой операторов можно получить a) единообразное поведение для любых типов (в том числе для тех, о которых разработчик библиотеки даже не догадывался) и b) расширение списка типов, на которые данная операция распространяется.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Pzz, Вы писали:
Pzz>>>Потом, constantness в C++ — понятие вообще довольно "плюшевое". В силу того, что C++ унаследовал от Си понятие о значении объекта, как о содержимом тех байтов памяти, из который состоит объект. TL>>Прямо скажем, это просто порочная практика "любителей копаться там, где никому больше не нужно": почему-то любимый вопрос на собеседовании "как по-вашему представлен экзепляр класса бинарно?" — на практике полезности не вызывает. :xz: Pzz>Я пытаюсь сказать несколько более глубокую вещь. Не то, что в C++ можно добраться до бинарной сущности объекта — ну можно и можно, и хрен бы с ним. А то, что в C++ нельзя спрятать эту бинарную сущность так, чтобы она никогда не вылезла при добросовестном использовании.
std::vector<int> const someIntegers(42u, 42);
там наверняка внутри три указателя — начало данных, конец данных, конец выделенной области памяти. Как ты этот вектор ни используй, данные ты не изменишь. Спрятано всё.
Pzz>Проблема в том, что в C++ управление памятью — ручное. Как его не оборачивай в темплейтные обертки, компилятор все равно не в курсе, что происходит с памятью. А без этого, видимо, высокоуровневый язык не построишь.
Открою секрет: в C++09 изо всех сил стараются добавить GC. Ручное управление памятью — не проблема.
TL>>Ну ладно: как ты то же самое ограничишь в Си? А никак. TL>>В тех же "плюсах" это может ограничить даже школьник, перебросив член в защищенную область и нарисовав публичные аксессоры. :user: TL>>Применить к C++ явно "сишный" подход и поставить факт в укор "плюсам" — :???: :no: :xz:
Pzz>На C++, на самом деле, тоже толком никак. Например потому, что конструктор не знает, конструирует ли он константный или mutable объект.
Это лишено смысла… X const x = X(); — здесь какой объект конструируется?
Здравствуйте, Maxim S. Shatskih, Вы писали:
Pzz>>Это плохая оптимизация — у нее слишком много тонких эффектов. Если что-то не может быть сделано прозрачно (а дешевая передача объектов в языке типа Си/C++ не может быть сделана прозрачно, в силу очень открытого интерфейса к реальной памяти машины), то лучше не делать этого вовсе.
MSS>Как хорошо, что Си не дает передавать структуры by value... и временных объектов не плодит...
Здравствуйте, Maxim S. Shatskih, Вы писали:
R>>Допустим есть некая незнакомая функция f(X* x).
MSS>Комментарии надо писать, и пользоваться T Array[] и T* Ptr.
Во-первых, это не защищает от возможности подумать, что можно передать 0.
Во-вторых, к сожалению, так пишет очень мало программистов, и главное разработчики библиотек типа WinAPI.
R>>Далее, т.к. указатели обычно не объявляются как константные
MSS>Можно и объявить. Как и ссылку.
Ссылки всегда константные.
Опять же понятно, что можно написать и [], и комментарий, и const. Но я говорю о реальной жизни. Достаточно открыть первую попавшуюся библиотеку и с вероятностью 80% там этого ничего не будет.
Здравствуйте, Maxim S. Shatskih, Вы писали:
C>>Лучше. Константные ссылки — это по сути оптимизация передачи по значению. В частности, очень частно это делается при передаче временных объектов. Если же брать на них указатель — то мы не можем знать сохранит ли вызываемый код где-то у себя. В случае со ссылками мы знаем, что вызываемый код не будет сохранять переданое ему значение (ну если его не идиоты пишут, конечно).
MSS>Вот про идиотов хорошая оговорка. Идиоты могут передать ссылку в конструктор какого-то класса и позвать его через new.
MSS>Можно в комментарии к функции оговорить время жизни объекта, и имеет ли право функция сохранять данный указатель где-то.
Это делается с помощью shared_ptr и weak_ptr, проще и надежнее.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Maxim S. Shatskih, Вы писали:
E>>>Как человек, которому на C++ довелось посчитать математику (в том числе и с матрицами комплексных чисел в 99-2000-й годах)
MSS>>Вот конкретно матрицы и есть тот редкий случай, когда operator — по делу.
E>Ну с матрицами вопрос спорный. operator[] для разных хитрых матриц -- да, по делу. А вот разные operator+ или operator* -- тут можно и к expression templates приплыть.
E>А вот примеры с std::complex или какими-то другими типами, выдающими себя за числа -- это как раз показательно.
Да. Причём таких примеров можно привести множество: даты и интервалы времени, суммы денег, числа произвольной длины, хранящиеся в строках и т.д.
MSS>>Почему не cout.output(i).output(j)?
E>Потому, что output -- это метод какого-то класса. И в C++ у меня нет возможности расширять чужой класс перегруженными методами для своих типов.
Хороший аргумент. Правда он не отменяет возможности писать:
Здравствуйте, Erop, Вы писали:
TL>>Ключевой момент был неоднократно упомянут и указан явно тоже: практик в _чем_ именно? E>В программировании довольно сложных систем. А Александреску практик в написании книжек...
Я в Линусе чайник: что еще кроме линукса Линус написал?
Здравствуйте, Sergey, Вы писали:
>>>> и с юниксными симлинками. >> S>Опять же, проблема пользователя. Не поддерживает ОС симлинки — не используй их. >> Если кто-то положил в репозиторий симлинк, как он должен выглядеть с точки зрения пользователя, который общается с системой контроля версий через виндовс?
S>Под вистой — как симлинк. Под более ранними — как ошибка.
Во-первых, здесь дело не в ОС, а в ФС, а во-вторых, какого рода ошибка?
Вообще, грустно в Windows без нормальных файловых систем. Например, FAT на флешках — это же издевательство над микросхемой…
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, The Lex, Вы писали:
TL>>Первый написал много толковых книг по вопросу практики примения одного из самых распространенных языков программирования современности. Что такого "архивеликого" сделал второй?
E>Зато второй -- практик...
Есть еще один практик, не менее великий, чем Торвальдст. Его зовут Кен Томпсон. Вот, что он когда-то говорил о Линуксе http://www.osp.ru/os/1999/04/179809/ ...
Здравствуйте, The Lex, Вы писали:
TL>Я в Линусе чайник: что еще кроме линукса Линус написал?
Не помню. Мни и линукса вполне достаточно. Это очень большой и серьёзный проект
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
По порядку, от сложного к простому
S>А никто и не предлагает интерфейсы плюсовые наружу выставлять...
Т.е. вернулись к началу ветки — к плоским COM-подобным интерфейсам (по сути — таблица с указателями на функции). Кроме того такое плоское апи уменьшает сцепление — оно не зависит даже от языка реализации интерфейса (это азы кома, вроде бы).
С классическими монолитными ядрами вроде уже никто не работает — динамически подружаемые модули составляют существенную часть работающего ядра. Апи подсистем ядра для этих модулей должно быть плоское. Подсистемы ядра общаються между собой и тоже, в идеале, должны обладать плоским апи (вдруг мы захотим сменить ну, например, шедулятор ). Но темлейты не дают нам такой гибкости, точнее, темплейты завернутые в плоский апи теряют всю свою темплейтность. Попробуйте придумать/написать плоскую обертку для stl — получиться что-то вроде at&tшной сdt (с кучей указателей на функции и void * в качестве контейнерного элемента).
Плоский апи — это границы применения темплейтов, также граница использования исключений, множественного наследование, rtti и прочих особенностей с++. Вроде бы сразу появляеться антипример — сильно-теплейтная АТЛ для плоского COM вполне существует и является вобщем state-of-art библиотекой. Но вот тут и возникает отличие — реализуя в коме свой IStream, вы одновременно реализуете свой ISequentialStream и свой IUnknown. Однако в ядре вы, реализуя свой IStream, должны использовать предоставленный системой ISequentialStream которой в свою очередь будет использовать предоставляемый системой IUnknown (это аналогия, не буквально). Допустим я пишу свой драйвер для сетевого юсб-девайса. Я должен предоставить интерфейс outputPacket(const void * raw, size_t size), зарегить его в системе и получить от системы интерфейс для юсб. В методе я заполняю USBPacket и вызваю у юсб-интерфейса метод usbSendCommand(USBPacket somePacket). Все. Тут (в заполнении структуры USBCommand) негде разгуляться всем фичам с++.
Кратко:
1) современное ядро ос не монолитно и представляет собой большое количество модулей, причем часть модулей подгружаеться/выгружаеться в рантайме.
2) модули выполняют какую-то одну относительно несложную задачу.
3) для выполнения каких-то запросов эти модули выстраиваются в стек и разные уровни стека между собой общаются на плоском апи.
В результате размеры и сложность этих модулей становятся небольшими, их внешние интерфесы — плоскими. А это ведет к тому что в ядре
1) не подходит тот шаблонный подход к проектированию, который используеться для билиотек типа стл, атл, буста.
2) полноценный с++ оказываеться просто не нужен, и полное его использование приводит к овердизайну.
Хотя принципиально никто не мешает использовать туже стл в ядре. Но вобщем никто и не мешает написать само ядро на пэ-ха-пэ или луа, у них есть даже одно преимущество перед с++ — сборка мусора
S>В бусте то ли уже появились, то ли вот-вот будут. А пока широко распространенных нету — и самому недолго написать.
Я понял — известных реализаций типа queue.h нет. Ну на нет и суда нет, хотя отелось бы посмотреть как это будет выглядеть в темплейтах с++.
S>Ситуация тут ровно та же, что и с макросами. И даже если все "руками написать", то — сюрприз — все равно две копии кода будут Так что в качестве аргумента против шаблонов — не катит.
тут не макросы vs шаблоны, а "шаблонный" подход к проектированию vs плоский комоподобный апи. А макросы против шаблонов почти всегда не катят — это очевидно.
S>С чего бы это система контроля версий вдруг стала system-level?
Требование к софту программеров и не_программеров разные (правда общий момент есть — чтобы работало и не глючило ). Поэтому ядро, службы/демоны, средства разработки — все то, что не решает проблемы пользователя-не_программиста я отношу к system-level. Возможно у меня сильно шырокое определение system-level , спорить не буду.
S>Лень мне по их исходникам лазить... А без изучения — какое может быть сравнение? Да и квалификацию писателей все равно не учтешь.
Да одинаковые у них квалификации, все системы одинаково часто сравниваються во всяких обзорах и обладают примерно одинаковой функциональностью (и багами). Неужели вы верите в с++гениев недооцененных серой толпой голо-cишных-питон-программеров .
TL>Я в Линусе чайник: что еще кроме линукса Линус написал?
7 лет назад был 15 мег зип с исходниками. Конечно, там не все один Линус писал, но он писал самые старые и фундаментальные вещи и еще и поддерживал все это как тимлид.