Похоже, мечтам о создании единого бездиалектного C++ не суждено будет сбыться.
Будущее C++ уже не первый год служит поводом для огромного количества разногласий.
Возможно, вы подумаете, что я говорю о профильных тредах на Reddit — местная публика давно славится своей многополярностью и любовью к спорам ради спора, так что разговоры на повышенных тонах там в принципе никогда не утихают. Однако гораздо страннее их видеть даже на официальных заседаниях комитета по стандартизации C++. Ниже я приведу несколько красноречивых примеров.
Текущее положение дел C++
Вот в какой интересной ситуации мы оказались в последнее время:
-
C++’s Evolution Working Group (EWG) недавно выпустила документ P3466 R0 — (Re)affirm design principles for future C++ evolution. Особенно интересно в разрезе статьи следующее:
Принято решение не менять ABI в целях сохранения совместимости с C и прошлыми версиями C++.
Не появится т.н. «паразитных аннотаций» (например, аннотаций времени жизни).
Целый набор взаимоисключающих целей: например, и ABI не поменяется, и zero-overhead principle по-прежнему в строю.
В то же самое время происходят другие, не менее интригующие события:
-
Правительство США выступает против использования языка C++:
Кроме шуток, различные ветви государственной власти США выпускают документ за документом, пропагандируя отказ от повсеместного использования языков с небезопасным доступом к памяти.
-
Представители Big Tech вовсю лоббируют переход к Rust:
Microsoft активно переписывает свои ключевые библиотеки на Rust.
Google также вкладывается в Rust, и фактически начала работу над двунаправленным инструментом взаимодействия C++/Rust.
AWS применяет Rust в своих продуктах.
И так далее, и тому подобное.
К слову о Big Tech, вы заметили, что Герб Саттер покинул Microsoft, а MSVC как-то чересчур неторопливо внедряет функции C++ 23 и просит у сообщества помощи в определении приоритетов.
После печально известного пражского ABI-голосования («В C23 ABI не претерпит изменений, и неясно, случатся ли они вообще») Google значительно сократила свое участие в процессе развития C и вместо этого начала работать над собственным языком-преемником C++. У них даже имеется документ с описанием проблем, с которыми они столкнулись при попытке «улучшить» C++.
В сообществе набирают популярность истории людей, которые в течение многих лет изо всех сил стремились принять участие в работе комитета по стандартизации C++, но их попросту пережевывали и выплевывали.
-
Модули до сих пор не имплементированы [Are we modules yet?](https://arewemodulesyet.org/)
«Профили безопасности» до сих пор находятся в состоянии «ни жива, ни мертва» и не получили какой-либо реализации. Шон Бакстер занял позицию против профилей и назвал C++ «недоспецифицированным».
Не знаю, какие выводы из этой информации сделали вы, но, на мой взгляд, все это напоминает развал C++. Кажется, будто комитет по C++ из последних сил справляется со своими обязанностями. Впрочем, я не хочу, чтобы вы поняли меня превратно. C++ сам по себе никуда не денется – речь идет именно о том, какое развитие он получит в ближайшие годы.
Две разные культуры C++
Всем приходится самостоятельно искать новые решения.
Возьмем для примера уже упомянутую выше компанию Google. Очевидно, Google потеряла веру в развитие C++ после голосования по ABI. Это не потеря веры в сам язык, у Google одна из самых больших кодовых баз на C++ в мире. Этот язык сослужил компании невероятную службу. Скорее, это потеря веры в способность языка развиваться в условиях давления сразу с нескольких сторон (актуальные и потенциальные постановления правительства, наличие языков-конкурентов, желание добиться более высокой производительности, гарантии безопасности от ключевых игроков и т. д.).
Но в чем же корневая проблема? Почему нельзя просто собраться всем миром, взять и…изменить C++ в нужную сторону?
Никакого секрета здесь нет. Просто взгляните, что Герб Саттер писал в своей статье о профилях:
Мы должны свести к минимуму необходимость изменения существующего кода. Что касается внесения изменений в существующий код, то многолетний опыт показывает, что большинство владельцев крупных кодовых баз не захотят и не станут менять даже 1% от общего объема кода для удовлетворения новых правил строгости, даже из соображений безопасности. Разве что их принудят к этому нормативные требования». — Герб Саттер
Круто. Кого-то это удивляет? Меня – ни капельки.
А теперь для контраста ознакомимся с фрагментом биографии Чендлера Каррута, представленной на его страничке на WG21:
Я руководил разработкой инструментария для C++ и систем автоматического рефакторинга, построенных на основе Clang и теперь являющихся частью проекта Clang.
[...]
В Google я возглавил направление, занимавшееся масштабированием автоматизированных инструментов рефакторинга на основе Clang на всю нашу кодовую базу, а это более 100 миллионов строк C++ кода. Теперь мы можем провести анализ, а затем и рефакторинг всей кодовой базы всего за 20 минут.
Ого. Видите это? (Конечно, видите, ведь я специально выделил жирным нужные части текста).
Речь идет про некий «автоматизированный инструментарий». Но за этими словами стоит гораздо больше. Автоматизированный инструментарий – это лишь вершина айсберга, единичный яркий пример.
По сути, сейчас мы наблюдаем конфликт между двумя кардинально отличающимися лагерями пользователей C++:
Относительно современные, компетентные технологические корпорации, которые понимают, что их код – это актив. (Это не обязательно представители big tech. Любой вменяемый стартап, пишущий свежий код на C++, также попадает в эту категорию).
Все остальные. Замшелые конторы, где люди до сих пор спорят о том, как правильно делать отступы, а молодой инженер умоляет руководство разрешить ему установить линтер.
Первая группа сможет адаптироваться к переходу на новые стандарты с наименьшими проблемами, поскольку она будет в состоянии собрать собственный стек C++ из исходников, полученных из репозиториев GitHub-проектов и пакетных менеджеров. (Примечание переводчика: Автор оригинальной статьи использует термин «версионированный источник») А вторая, по-прежнему использующая устаревшие предсобранные библиотеки из 1998 года, будет обречена на страдания.
Умение собрать весь стек зависимостей из исходников нужных версий (желательно еще и с автоматизированными тестами) – это, пожалуй, самое важное отличие между двумя лагерями.
На практике, конечно, чаще встречается нечто среднее. Представляю, сколько пота, слез, денег и крови утекло, чтобы превратить огромные кодовые базы из ужасающих клубков грязи в полууправляемые, собираемые, линкуемые и чуть менее ужасающие клубки грязи.
Теперь, оглядываясь назад, легко рассуждать о неизбежности этих процессов: существовало явное несоответствие между потребностями корпораций вроде Google (которые используют относительно современный C++, имеют автоматизированный инструментарий и тестирование, а также современную инфраструктуру), и огромным интересом всего остального мира к обратной совместимости.
Если говорить на чистоту, то идея единого, свободного от диалектов и унифицированного C++, похоже, умерла уже много лет назад. C++ сейчас существует в мире в двух агрегатных состояниях:
Любой относительно современный C++. Все собирается из исходников подходящей версии посредством специального унифицированного сборщика, который, по крайней мере, немного сложнее, чем голый CMake, и выглядит как вполне адекватно работающий, если слегка прищуриться. Всякие статические анализаторы, форматировщики, линтеры. Любое соглашение о необходимости поддерживать кодовую базу чистой и современной в этом случае бесценно. Возможно, даже C++17, с unique_ptr, constexpr, optional и лямбдами. Но это не самое главное. Важнее всего инструментарий.
Устаревший C++. Все, что отличается от написанного выше. Любой C++, который засел в древних, запыленных серверах какого-нибудь банка. Любой C++, который опирается на кусок непонятно кем и когда скомпилированного кода. Исходники давно утеряны, а авторы наверняка на том свете. Любой C++, развернутый на любительском сервере настолько криво, что его перенос на новое место займет у инженера целый месяц, поскольку ему придется разобраться со всеми неявными зависимостями, конфигурациями и переменными окружения. Любая кодовая база, которая больше напоминает не актив, а черную дыру, засасывающую деньги. Любой код, в котором сборка бинарника из исходного кода требует больше пары нажатий кнопок или вообще невозможна.
Обратите внимание, основное различие заключается не в самом C++. В первую очередь это инструментарий и возможность сборки из исходного доступного через систему контроля версий кода любым чистым, четко определенным способом. В идеале, даже возможность развертывания без необходимости помнить о флагах или переменных окружения, которые обычно устанавливал предыдущий разработчик, чтобы все не рухнуло.
То, насколько кодовая база Google соответствует «современным» стандартам C++, в значительной степени вторично по отношению к тому, насколько хорош ее инструментарий и можно ли собрать проект из исходников без танцев с бубном.
Многие здесь возразят, мол, комитет по стандартизации C++ никак не отвечает за инструментарий, и они будут правы. Это сделано намеренно: комитет в ответе за спецификацию языка C++, а не конкретные реализации.
К слову о Go. Если в Go и есть что-то хорошее, так это инструментарий. C++ по сравнению с ним – это натуральный мамонт. У C++ нет единой системы сборки, ничего даже близко похожего на единую систему управления пакетами, а еще его невероятно сложно разбирать и анализировать (это очень важно с точки зрения инструментария).
Между описанными выше лагерями (хороший инструментарий, можно без усилий собрать всё из исходников, против плохого инструментария, нельзя ничего собрать из исходников) существует огромный, постоянно увеличивающийся разрыв, и я, честно говоря, не думаю, что в ближайшее время он будет ликвидирован.
Комитет по C++, кажется, очень привержен поддержанию обратной совместимости, поэтому и не считается с ценой, которую приходится за нее платить.
Я не могу здесь однозначно принять чью-то сторону. Многим обратная совместимость совершенно необходима, причем по крайне веским причинам. Другим она попросту не нужна. Нельзя говорить, что кто-то из них не прав: это всего лишь разные, взаимоисключающие взгляды на проблему.
Последствия
Именно поэтому вопрос с профилями уже почти два года никуда не движется: их имплементация нужна не для разрешения проблем современных, продвинутых в технологическом плане корпораций, использующих C++. Перед ними стоит совершенно другая задача: привнести в язык улучшения, не требующие переписывать старый код.
То же самое касается и модулей. Предполагается, что можно будет «всего-навсего» импортировать заголовочный файл как модуль, и при этом не возникнет никаких проблем с обратной совместимостью.
Конечно, всем нравятся функции, улучшающие язык, внедрение которых не повлечет за собой необходимость переписывать старый код. Поэтому, очевидно, и разрабатываются они с прицелом на «устаревший» C++. И любая функция, которая потребует перехода с «устаревшего» C++, для комитета C++ не имеет смысла, поскольку, как сказал Герб Саттер, нельзя ожидать, что все просто возьмут и перейдут на новую версию языка.
(Повторюсь, создавать функции с учетом «устаревшего» C++ вовсе не плохо. Это вполне разумное решение.)
Вот, о чем я стараюсь помнить, когда читаю статьи о C++: у него есть две большие целевые аудитории. Одна – современная, другая – традиционная. Эти два лагеря сильно расходятся во мнениях, и многие статьи пишутся с учетом потребностей какой-то одной конкретной группы.
Это порождает в сообществе споры и кривотолки: что бы там кому ни казалось, профили безопасности и Safe C++ пытаются решить совершенно разные проблемы двух разных аудиторий.
Комитет по C++ стремится не допустить увеличения этого раскола. Вероятно, поэтому все, что делает Шон Бакстер в ключе Safe C++, для них не имеет смысла. Это радикальное, масштабное изменение, которое может создать принципиально новый способ работы с C++.
Конечно, здесь может возникнуть другой вопрос: а не являются ли конкретные члены комитета по стандартизации C++ обыкновенными упрямцами, которые хватаются за последнюю соломинку, лишь бы не допустить в языке эволюции, с которой они лично эстетически не согласны.
Не мне судить кого-либо, но я не впервые слышу, что комитет по C++ придерживается двойных стандартов. Вот, например: «Мы ожидаем от вас полной, рабочей реализации в нескольких компиляторах, если вы хотите, чтобы это предложение было одобрено, но при этом с радостью возьмем на себя обязательства по ряду обширных проектов (например, по модулям или профилям), которые до сих поре не имеют работающей реализации».
Если так и есть, то я не знаю, как долго аудитория C++ еще просуществует в относительно целостном виде.
И всё это – при условии, что ABI в ближайшее время не будет подвергаться изменениям.
Комментарии (122)
NeoCode
19.12.2024 15:48Непонятно в чем проблема иметь несколько ABI. Старые, новые, от сторонних компиляторов и языков программирования...
Tim7456
19.12.2024 15:48В том, что существует куча софта который уже не собирается последними компиляторами, либо существует ТОЛЬКО в бинарном виде. Этот софт (суммарно) тянет на триллионы долларов (стоимость замены). Если начнете играть с совместимостью нескольких ABI, то это все придется изобрести заново. И кто-то должен будет за эти работы заплатить. А добровольцев платить что-то не видно.
slonopotamus
19.12.2024 15:48У меня для вас новости! Несколько ABI и так уже есть: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
И в Windows тоже их несколько. Видели вот эти вот msvcrt2005, msvcrt2008, msvcrt2010, etc? Это ни что иное как несовместимые между собой по ABI версии стандартной библиотеки C++: https://learn.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=msvc-170
vadimr
19.12.2024 15:48Вообще не понимаю, зачем кому-либо может понадобиться гипотетический С++ без обратной совместимости. Писать всё заново с нуля на языке идейно во многом 50-летней давности, который даже и в момент своего появления 50 лет назад был далеко не самым продвинутым... чтобы что?
Sun-ami
19.12.2024 15:48Напрашивается вывод, что нужен отдельный язык со всеми современными возможностями C++, но без груза совместимости, которая тянет за собой небезопасность из-за многочисленных вариантов неопределённого поведения.
vadimr
19.12.2024 15:48А какие полезные возможности есть в C++ по сравнению с другими языками, кроме кодовой базы?
Если по-честному, то C++ сам по себе - это гибрид недосмолтока 90-х с недохаскелем 2000-х, примотанный изолентой поверх Си.
Sun-ami
19.12.2024 15:48Универсальность, которая позволяет совмещать высокоуровневые и низкоуровневые подходы в рамках одной программы. Другими словами, писать большие программы, и максимально оптимизировать их там, где это требуется, причём принимать решение о необходимости оптимизации в любой момент, и не слишком сложно выполнять его.
KivApple
19.12.2024 15:48В C++ в отличии от того же Rust есть, например, ООП с наследованием и т. п. Есть varidadic templates.
Многие решения C++ не очень элегантны (или даже очень уродливы), но он умеет буквально всё всеми способами (кроме разве что рефлексии, но и это уже добавляют) и при этом является компилируемым языком с ручным управлением памятью (что важно для задач, где требуется производительность).
Его конкуренты в основном предлагают гораздо более opionated решения типа "вы обязаны выбирать композицию вместо наследования".
vadimr
19.12.2024 15:48Хотелось бы отметить, что слухи о влиянии ручного управления памятью на производительность сильно преувеличены. Я как раз недавно в статье приводил пример, когда в очень неудобной экпоненциально сложной задаче происходил перебор огромнейшего количества динамически создаваемых и разрушаемых списков (в несколько раз больше объёма оперативной памяти). И вот в такой задаче автоматическая сборка мусора заняла всего 50% времени выполнения. Это по сути вообще ни о чём, на реализацию ООП в C++ уходит гораздо больше оверхеда (по сравнению с С).
На мой взгляд, ручное управление памятью в наше время (т.е. при том обычном соотношении ресурсов процессора и памяти, которое есть сейчас, и при современном состоянии алгоритмов сборки мусора) – это либо очень узкая область низкоуровневых задач (но даже там лучше память выделять вообще в статические массивы), либо лютый бабушкин анахронизм.
Никто, за редчайшими исключениями, не пишет на ассемблере, чтобы ускорить свою программу в 2 раза, хотя это вполне реально. Но мусор почему-то многие собирают руками. Парадокс.
Плохая репутация автоматической сборки мусора сложилась во времена машин с очень ограниченной оперативной памятью, когда каждый байт был на счету, и мусор приходилось собирать очень часто. А теперь действует инерция.
KReal
19.12.2024 15:48А можно ссылку на статью? Как-то прошла мимо меня..
vadimr
19.12.2024 15:48https://habr.com/ru/articles/859758/
В разделе недетерминированного программирования. Правда, я это не сразу туда дописал, так что если Вы прочли статью в первой редакции, то этого материала просто не было.
feelamee
19.12.2024 15:48Но мусор почему-то многие собирают руками
не понял о C++ ли вы, но я ОЧЕНЬ редко пишу free/delete.
Фактически мусор собирает компилятор благодаря raii
eao197
19.12.2024 15:48И вот в такой задаче автоматическая сборка мусора заняла всего 50% времени выполнения. Это по сути вообще ни о чём
Наверное, я чего-то не понимаю в программировании, но когда половина времени уходит не на полезную работу, а на менеджмент памяти, то в этом нет ничего хорошего. А когда это еще и характеризуют как "по сути ни о чём", то такое ощущение, что не понимаю я вообще ничего.
это либо очень узкая область низкоуровневых задач (но даже там лучше память выделять вообще в статические массивы), либо лютый бабушкин анахронизм.
Либо работа с большими объемами данных, где экономия 4-х байт на каждый объект приводит к снижению потребления памяти на сотни мегабайт. А с учетом того, что быстрые кэши маленькие, а загрузка в них данных из ОП медленная, то экономия на потребляемых объемах как-то сама собой трансформируется в выигрыш по скорости.
vadimr
19.12.2024 15:48Надо ж, какой пафос! Я б ещё, может, и мог с огромным усилием поверить, что в ваших программах негде сэкономить 4 байта, кроме как на счётчике ссылок, и вот именно он разрушил бы всё оптимальное размещение в памяти. Но уж никак не в объектно-ориентированном языке C++ с повсеместными таблицами виртуальных методов, длинами векторов и прочей шнягой поддержки выполнения. С Фортраном 77 такая аргументация прошла бы, а тут вряд ли.
Наверное, я чего-то не понимаю в программировании, но когда половина времени уходит не на полезную работу, а на менеджмент памяти, то в этом нет ничего хорошего. А когда это еще и характеризуют как "по сути ни о чём", то такое ощущение, что не понимаю я вообще ничего.
Ну ничего не могу поделать. Для большинства программ мне действительно совершенно неважно, будут или их действия выполняться за одну или за две миллисекунды. А вот время, затраченное на кодирование и отладку, и надёжность программы могут представлять интерес.
eao197
19.12.2024 15:48Надо ж, какой пафос!
Вы в моих словах нашли пафос? Перечитайте, пожалуйста.
Я б ещё, может, и мог с огромным усилием поверить, что в ваших программах негде сэкономить 4 байта, кроме как на счётчике ссылок, и вот именно он разрушил бы всё оптимальное размещение в памяти.
С чего вы взяли, что речь идет о счетчиках ссылок?
Ручное управление памятью (по крайней мере в моем мире) -- это не только ручной вызов new/delete (или malloc/calloc/free), и даже не деление на стек/хип. Это еще и использование union-ов, пулы/арены памяти и placement new. А так же агрегирование данных, когда вы объект класса A можете сделать полем класса B и память для A будет частью памяти для B (тогда как в языках с GC если у вас A -- это ссылочный тип, то частью другого ссылочного типа B вы его не сделаете).
Но уж никак не в объектно-ориентированном языке C++ с повсеместными таблицами виртуальных методов, длинами векторов и прочей шнягой поддержки выполнения.
Зная как вы не можете в обоснование собственных утвержений я даже и не стал заострять внимание вот на этом: "на реализацию ООП в C++ уходит гораздо больше оверхеда (по сравнению с С)". Но раз вы сами завели эту шарманку, то может поделитесь цифрами о том, насколько рукопашная реализация ООП на чистом Си выгоднее, чем поддерживаемая компилятором и рантаймом в С++?
vadimr
19.12.2024 15:48А я разве говорил про рукопашную организацию ООП? Я имею в виду чисто процедурный стиль.
eao197
19.12.2024 15:48А я разве говорил про рукопашную организацию ООП?
Вы сказали вот что:
"Это по сути вообще ни о чём, на реализацию ООП в C++ уходит гораздо больше оверхеда (по сравнению с С)."
Это сложно воспринять как-то иначе как накладные расходы на ООП в C++. А так как в чистом Си ООП нет, то когда в Си нам придется использовать ООП, то мы будет делать это вручную и обойдется нам это дешевле, чем в C++.
Я имею в виду чисто процедурный стиль.
Тогда при чем здесь ООП в C++? На C++ вы точно так же (даже надежнее и безопаснее) сможете использовать процедурный стиль, как и в Си.
Или вы в C++ видите какие-то дополнительные издержки даже на процедурный стиль в сравнении с Си?
vadimr
19.12.2024 15:48Если в C++ писать в стиле C, то зачем тогда C++?
А если писать в стиле C++, то получается оверхед. Я не против оверхеда самого по себе, но не надо тогда говорить о великой эффективности.
eao197
19.12.2024 15:48Если в C++ писать в стиле C, то зачем тогда C++?
Я не говорил о том, чтобы писать на C++ в стиле Си. Читайте внимательнее, пожалуйста.
Речь шла о том, что в C++ вы запросто можете программировать в процедурном стиле, как и на Си. Только делать это будет удобнее и надежнее. За счет, например, наличия ad-hoc полиморфизма, ссылок и отсутствия неявных преобразований из void*.
vadimr
19.12.2024 15:48Против отсутствия неявных преобразований из void* я не возражаю. Но для аргументации в пользу C++ в целом этого маловато.
eao197
19.12.2024 15:48А я и не аргументировал в пользу C++, я просил вас привести подтверждения того, что у C++ больше накладных расходов на поддержку ООП, чем в Си.
Вы, ожидаемо, в подтверждение собственных слов не смогли.
vadimr
19.12.2024 15:48Я писал, что накладные расходы C++ возникают именно из-за поддержки ООП. А про поддержку ООП на Си - это ваши фантазии. Я к такому не призывал.
Я вовсе не агитирую делать подобие C++ из других языков.
eao197
19.12.2024 15:48Я писал, что накладные расходы C++ возникают именно из-за поддержки ООП
Уже несколько раз цитировал что именно вы написали, повторяться не буду. Просто еще раз напомню, что рассуждать о накладных расходах на что-то по сравнению с чем-то можно только в случае, если это "что-то" есть в том самом "чем-то". В Си ООП нет, поэтому оценивать накладные расходы C++ на ООП в сравнении с Си бессмысленно. Не удивительно, что фактически подтвердить свои утверждения вы не можете.
vadimr
19.12.2024 15:48Именно потому, что в Си ООП нет, то накладные расходы на ООП в Си равны нулю. Не знаю, как уж понятнее объяснить.
eao197
19.12.2024 15:48Именно потому, что в Си ООП нет, то накладные расходы на ООП в Си равны нулю.
Да, да, да. Поэтому когда в каком-нибудь Си-шном проекте, типа OpenSSL, потребуются аналоги виртуальных функций, которые колхозятся на структурах с указателями на функции, то это все абсолютно бесплатно. Ага.
vadimr
19.12.2024 15:48Согласитесь, что аналоги виртуальных функций приходится колхозить очень редко по сравнению со случаями использования функций и структур данных вообще.
eao197
19.12.2024 15:48Ну расскажите, пожалуйста, какие накладные расходы на ООП есть, например, у std::vector, у которого нет виртуальных методов, но есть инкапсуляция.
vadimr
19.12.2024 15:48Например, вектор векторов не образует в памяти регулярную структуру, такую как массив массивов, что делает невозможной оптимизацию доступа и векторизацию по двум индексам.
eao197
19.12.2024 15:48Повторю вопрос специально для вас: "какие накладные расходы на ООП есть, например, у std::vector, у которого нет виртуальных методов, но есть инкапсуляция".
vadimr
19.12.2024 15:48Я, вроде, вам ответил. Это и есть в данном случае накладные расходы на ООП в части инкапсуляции.
vadimr
19.12.2024 15:48Что именно в ответе Вам непонятно?
Инкапсулировали массив в std::vector – получайте неэффективный доступ по двум индексам.
vadimr
19.12.2024 15:48Был вопрос про сам вектор.
Так-то и mdspan не нужен, достаточно выковырять из вектора массив и обойтись умножением. Только это не ответ на заданный вопрос.
vadimr
19.12.2024 15:48Разве в питоне или джаве нельзя сделать агрегированный тип?
eao197
19.12.2024 15:48А вы понимаете разницу между ссылочными типами (reference types) и типами-значениями (value types) в языках с GC?
Если у вас в Java тип A -- это reference type, т.е.:
public class A {...}
то когда вы делаете член типа A в классе B (который так же reference type):
public class B { private A a; ... }
то в B у вас хранится только ссылка на экземпляр A. И вы не можете повлиять на накладные расходы, связанные с хранением самого A и представлением ссылки на A внутри B.
vadimr
19.12.2024 15:48На накладные расходы, связанные с хранением самого A, вы в любом случае не можете повлиять, агрегируя A в другой класс.
А где у вас хранится в памяти тело агрегированного объекта относительно тела агрегирующего - это просто деталь реализации. В C++ всё равно так и так любой объект должен иметь возможность представляться ссылкой, так что сложно представить, как это различие можно практически эксплуатировать без ub. Сэкономить один указатель?
eao197
19.12.2024 15:48На накладные расходы, связанные с хранением самого A, вы в любом случае не можете повлиять, агрегируя A в другой класс.
Правда? А если смогу?
А где у вас хранится в памяти тело агрегированного объекта относительно тела агрегирующего - это просто деталь реализации.
Ну да, ну да. Абсолютно несущественная, особенно если брать в расчет cache locality.
В C++ всё равно так и так любой объект должен иметь возможность представляться ссылкой, так что сложно представить, как это различие можно практически эксплуатировать без ub.
Простите не распарсил.
А можно встречный вопрос: вы вообще на C++ программировали?
vadimr
19.12.2024 15:48Ну да, ну да. Абсолютно несущественная, особенно если брать в расчет cache locality.
Вы так уверены, что вам всегда будут одновременно нужны для обработки все поля агрегирующего объекта, в том числе и агрегируемый? Может, наоборот, вы забьёте кеш лишними данными?
А можно встречный вопрос: вы вообще на C++ программировали?
Нет, что вы, так рассуждаю. Но ваша правда в том, что погружаться в это тянет редко.
Простите не распарсил.
Так как любой объект в C++ (как и в других ООП языках) представляется таким образом, чтобы могла существовать самостоятельная ссылка на него, даже если он агрегирован в другой объект, то остаётся только простое его перемещение в памяти внутрь и наружу тела агрегирующего объекта, чем вы ничего существенного не достигнете.
Даже если предположить, что локальность в памяти агрегируемого объекта относительно агрегирующего что-то позволит выиграть в плане оптимизации (что ниоткуда само по себе не следует), то никто не мешает компилятору разместить в памяти вынесенный агрегированный объект сразу до или после агрегирующего. Фактически это скорее всего и произойдёт, так как они размещаются одновременно. Разница будет в один указатель.
eao197
19.12.2024 15:48Вы так уверены, что вам всегда будут одновременно нужны для обработки все поля агрегирующего объекта, в том числе и агрегируемый? Может, наоборот, вы забьёте кеш лишними данными?
Если не нужны, то я могу разнести A и B. Или могу переместить A внутри B.
Нет, что вы, так рассуждаю.
Оно и заметно.
Даже если предположить
Может хватит ваших предположений? Давайте с фактами, а то у вас с этим как-то туго пока. Слов много, фактов нет.
что ниоткуда само по себе не следует
Еще как следует, когда у нас один объект внутри другого, а не два в разных местах.
то никто не мешает компилятору разместить в памяти вынесенный агрегированный объект сразу до или после агрегирующего
Можно ли увидеть примеры сего чуда? Это во-первых.
Во-вторых, вот у вас будет нечто вида:class B { private C c = new C(); private D d = new D(); private A a = new A(); ... }
Где конструкторы C и D генерят тучу собственных мелких (или не очень) объектов. Как компилятор поймет, что рядом с B нужно размещать именно A?
Разница будет в один указатель.
Разница в один указатель -- это в два раза больше, чем те четыре, которые я привел в качестве примера.
vadimr
19.12.2024 15:48Может хватит ваших предположений? Давайте с фактами
А факты такие, что нет выраженной корреляции быстродействия реально используемых программ с языком, на котором они написаны. Тормозных программ на C++ столько же в процентном отношении, как и на других языках.
eao197
19.12.2024 15:48Прекрасно, начиналось все с
на реализацию ООП в C++ уходит гораздо больше оверхеда (по сравнению с С)
а закончилось общими фразами
нет выраженной корреляции быстродействия реально используемых программ с языком, на котором они написаны
Да вы просто мастер аргументировать вами же высказанные утверждения.
Тормозных программ на C++ столько же в процентном отношении, как и на других языках.
Только вот тормозят C++ программы несколько не так, чем программы на Ruby, например.
vadimr
19.12.2024 15:48Вы удивительный человек, который находит альтернативный смысл в самых очевидных утверждениях. Действительно, мою фразу
на реализацию ООП в C++ уходит гораздо больше оверхеда (по сравнению с С)
теоретически можно понять так, что мы будем на Си реализовывать ООП тоже. Но я этого, конечно, не имел в виду. А имел в виду, что, программируя на С++, мы будем вынуждены, в отличие от Си, использовать реализацию ООП, так как на ООП построены библиотеки С++ и практика программирования на С++.
eao197
19.12.2024 15:48Но я этого, конечно, не имел в виду.
Вот и приходится выяснять что же вы имели в виду.
Теперь же, когда выяснили, вы приведете какие-то цифры, подтверждающие ваше утверждение? Или после общих слов о том, что все тормозят одинаково в процентном отношении относительно всего остального (или что вы там имели в виду) никаких количественных оценок уже не предполагается?
А имел в виду, что, программируя на С++, мы будем вынуждены, в отличие от Си, использовать реализацию ООП, так как на ООП построены библиотеки С++ и практика программирования на С++.
Тут бы очень хотелось выяснить кто такие "мы".
А практика программирования на C++ уже давным-давно (лет 25 минимум, а то и все 30) держится на мультипарадигменности, где ООП соседствует как с обычным процедурным подходом, так и с обобщенным программированием.
vadimr
19.12.2024 15:48Только вот тормозят C++ программы несколько не так, чем программы на Ruby, например.
Не в секундах?
Chaos_Optima
19.12.2024 15:48Что-то вы чушь какую-то пишете, если я напишу например
struct matrix { float4 row1, row2, row3, row4; }
то Матрица будет размерностью 16*sizeof(float)
Это будет memory friendly и cache friendly и simd friendly в отличии от той же java это даст гигантский прирос производительности при массовой обработке
vadimr
19.12.2024 15:48Только вот беда, в реальной прикладной программе на C++ такой структуры matrix не будет (например, потому, что массивы в С++ должны иметь константные размеры). А будет там какой-нибудь класс Matrix на базе векторов, который будет работать в 5 раз медленнее, чем питоновская библиотека numpy (которая, правда, сама написана на Си, но для Питона входит в стандартное окружение, а для C++ нет).
Можно, конечно, построить синтетический пример в вашем духе. Но в реальной массе программ на 99% всё будет не так.
eao197
19.12.2024 15:48Только вот беда, в реальной прикладной программе на C++
Отучаемся говорить за всех (c)
vadimr
19.12.2024 15:48Лестная ссылка, конечно, но давайте проверим реальную практику программирования на С++:
https://github.com/usmana5809/Matrix-Operations-Cpp
Тут просто всегда матрицы 10x10.
https://github.com/akalicki/matrix
Тут так:
void Matrix::allocSpace() { p = new double*[rows_]; for (int i = 0; i < rows_; ++i) { p[i] = new double[cols_]; } }
Где тут локальность в памяти?
https://gist.github.com/vnkdj5/5a33e530facb17f2dcf8bb88508cb4cd
Тут просто всегда матрицы 5x5.
https://github.com/bezlant/s21_matrix_cpp
Тут умный программист попался, использовал просто старый добрый одномерный массив безо всяких агрегаций:
matrix_ = new double[rows_ * cols_]();
https://github.com/Abhrankan-Chakrabarti/Interactive-Matrix-Calculator
Тут всегда 10x10.
https://github.com/omaraflak/Matrix
Тут прямо то, о чём я писал:
Matrix<T>(std::vector<std::vector<T> > const &array);
Ну и т.д.
Конечно, умный человек и кривой инструмент найдёт способ приспособить к делу удачным образом, но это ж не повод делать инструмент кривым.
eao197
19.12.2024 15:48Вы бы еще за демонстрациями на говнокод.ру сходили бы. Единственный из показанных вами репозиториев, который имеет хотя бы нормальное количество звезд -- 99 на данный момент -- содержит просто лабы по программированию: "A simple mathematical matrix class written in C++ to be reused for future assignments in my Computational Linear Algebra class."
Да еще и с откровенной припиской: "The code almost definitely constains significant bugs and solves numerous problems in a naive, inefficient, and incomplete manner."
vadimr
19.12.2024 15:48Ну так язык программирования является инструментом для его фактических пользователей. Что можно поделать, если они такие вот? Я их не отбирал специально, просто загуглил.
Я не сомневаюсь, что лично Вы умный программист, хотя и со скверным характером, и напишете на C++ гораздо лучше, чем эти люди. Но толку-то с этого, если Ваша программа утонет в океане вот этого вот говнокода, который является типичной практикой современного программирования?
eao197
19.12.2024 15:48Ну так язык программирования является инструментом для его фактических пользователей.
А теперь еще раз, может быть сейчас поймете: отучаемся говорить за всех.
eao197
19.12.2024 15:48Простите, но вашей глупости, выражающейся в афигительных формулировках, с меня достаточно. Ваша фраза -- "в реальной прикладной программе на C++ такой структуры matrix не будет" -- не содержит никаких ограничений, т.е. может трактоваться как "в любой реальной программе".
Так вот, не в любой. Отсюда и просьба к вам не говорить за всех, т.е. вводить ограничения в ваши высказывания. Чтобы можно было понять, что речь идет о "виденных вами лично" программах на C++, или о "написанных вами лично программах на C++", или о специально раскопанных вами на помойках фрагментах говнокода на C++, про который забыли даже его авторы.
vadimr
19.12.2024 15:48Если бы я хотел написать “в любой”, я и написал бы “в любой”. Если я не написал “в любой”, значит не в любой. Разве это непонятно?
Я пишу о статистически значимой выборке. Которую я специально не раскапывал, а просто взял подряд имеющуюся практику программирования с гитхаба, в отличие от приводившихся здесь синтетических примеров.
Естественно, что при этом каждый пишет о виденном им лично, ничего другого не существует в объективном восприятии. Ну, разве что мифы.
Chaos_Optima
19.12.2024 15:48Нет вы приводите в пример первые попавшиеся лабы, тогда как в мире нормально разработки используются готовые библиотеки, посмотрите реализацию у directxmath, Sony math, unreal, godot и куче других, графических или физических движков, и там везде будет примерно то что написал я, а в mkl матрици например на шаблонах будут, любой размерности.
vadimr
19.12.2024 15:48Вопрос использования готовой библиотеки вообще не имеет отношения к языку C++ или любому другому. Эту библиотеку можно использовать из любого языка, имеющего к ней интерфейс. А сама библиотека, если она написана умными людьми, то, конечно, будет написана эффективно.
Многие физические библиотеки написаны на Фортране, но это же не является достоинством Фортрана как языка программирования в общем контексте, не так ли?
Chaos_Optima
19.12.2024 15:48Эмммм. Не хочу вас расстраивать (хотя нет хочу и даже очень) но именно такие матрицы используются практически везде, начиная от игровых движков и заканчивая гигантскими матрицами для нейронок
Kealon
19.12.2024 15:48Плохая репутация GC сложилась уже в текущее время. Утечки памяти сейчас одна из сильнейших проблем программ с GC. Что иронично :-)
А в программах с ручным управлением эти проблемы уже почти не возникают.
Medeyko
19.12.2024 15:48А не вписываются ли Rust и/или Carbon в то, что Вы сформулировали?
Rust уже получил определённое распространение, о чём говорится и в обсуждаемой статье. Но достаточно заметно отличается от C++.
Carbon ещё в процессе начальной разработки, minimum viable product версия 0.1 ожидается в 2025 году, а production ready 1.0 - в 2027. Но зато создаётся под эгидой упомянутого в обсуждаемой статье Чендлера Каррута в Google, с сохранением двусторонней совместимости с C++ (за счёт автоматической конвертации; по синтаксису, на мой взгляд, больше выглядит похожим на Rust, чем на C++). Тоже упомянут в обсуждаемой статье.
Эти языки не являются решениями, соответствующими сделанному Вами выводу?
NeoCode
19.12.2024 15:48Сейчас все новые языки будут "похожими на Rust" - как я понимаю, в целях упрощения парсинга и исключения неоднозначностей фундаментально отказались от "сишного" стиля объявления переменных и функций.
fen-sei
19.12.2024 15:48Полноценной поддержки ООП в Расте, увы, нет. :-(
(про Карбон не знаю, а в Гоу кастрация под корень)
feelamee
19.12.2024 15:48все кроме наследования, которое итак почти является анти-паттерном и во многих местах лучше использовать композицию/агрегацию.
Вполне полноценное ООП как по мне
vadimr
19.12.2024 15:48Наследования в расте нет.
Полиморфизма полноценного нет ни в расте, ни в C++, потому что он требует динамической типизации.
ООП = struct ?
Тогда самый ООП язык – это Кобол, там инкапсуляции больше всего.
slonopotamus
19.12.2024 15:48Полиморфизма полноценного нет ни в расте, ни в C++, потому что он требует динамической типизации.
Шаблоны/дженерики - статический полиморфизм. dyn trait/virtual - динамический полиморфизм. Чем это неполноценно?
vadimr
19.12.2024 15:48Вообще ООП и его терминология пошли из Смоллтока. Что такое полиморфизм с точки зрения Смоллтока? Это такое положение дел, когда объект априорно ничего не знает о типе другого объекта, с которым он взаимодействует.
Например, условно, я определяю функцию half(x) как x/2. И при этом мне нафиг не нужно знать, в чём состоит смысл и реализация операции деления (а также двойки) и какой тип у переменной x. Потом когда-нибудь кто-то реализует, скажем, арифметику рациональных чисел со своим делением, а моя функция half всё так же будет работать с этими рациональными числами. И для этого даже перекомпиляция half будет не нужна, не говоря уж об априорном знании типа аргумента.
eao197
19.12.2024 15:48Вообще ООП и его терминология пошли из Смоллтока.
Конкретно в C++ ООП и его терминология пришли из Simula 67, который появился за несколько лет до начала работ над SmallTalk-ом.
vadimr
19.12.2024 15:48Синтаксис объектно-ориентированных конструкций в С++ действительно имеет много общего с Симулой 67. Однако сам термин ООП и основные принципы ООП были придуманы Аланом Кеем при работе над Смоллтоком. Симула 67 была фактически зачислена в объектно-ориентированные языки задним числом, но никто там про тройку инкапсуляция-наследование-полиморфизм не думал.
eao197
19.12.2024 15:48Ну да, ну да. ООП было, а слова такого не было, ага.
То, что Алан Кей хорош в самовосхвалении не означает, что ООП -- это только то, что вышло из SmallTalk и имеет отношение к SmallTalk.
Но даже это не важно. Вы сослались на SmallTalk, но так и не объяснили почему для полиморфизма нужна динамическая типизация.
И вряд ли это у вас получится, т.к. полиморфизм бывает разный. И, сюрприз, C++ поддерживает несколько их видов. Можно выбирать на вкус.
KivApple
19.12.2024 15:48На практике антипаттерн наследование или нет зависит от предметной области и задачи.
C++ даёт выбор. Rust не даёт.
Sun-ami
19.12.2024 15:48Rust не поддерживает ООП так, как С++. С Carbon ситуация вроде бы лучше, но у него синтаксис довольно существенно отличается от С++. Нужен такой язык, перенос на который кода с C++, в котором применяются только актуальные практики программирования, не потребует вообще никаких правок кода. То есть это должен быть не совсем новый язык, а просто более строгая версия C++, ограниченно-совместимая с просто С++. Какой-то Safe C++.
Chaos_Optima
19.12.2024 15:48Чем cppfront не подходит? По-моему самое то для с++
Sun-ami
19.12.2024 15:48Cppfront подходит, с ним можно пойти дальше, в частности изменив для него ABI. Моя идея состоит в том, что хватит бесконечно выпускать новые стандарты C++, которые делают его уже по сути другим языком, и всё больше усложняют его изучение, а вместо этого нужно перейти на приемника C++, такого как cppfront, и дальше вносить большие изменения уже в него, не таща за собой всё небезопасное наследство C++, подобно тому, как в своё время перешли с C на C++. При этом компиляторы могут поддерживать оба языка, подобно тому, как сейчас они поддерживают C и C++.
slonopotamus
19.12.2024 15:48Если в Go и есть что-то хорошее, так это инструментарий.
Я аж кофе подавился. Нет, в Go плохой инструментарий.
feelamee
19.12.2024 15:48будьте осторожны с кофе.
Но не забывайте аргументировать свои утверждения
slonopotamus
19.12.2024 15:48Ну неплохо бы сначала увидеть аргументацию изначального утверждения.
feelamee
19.12.2024 15:48далее автор и описал, чем он руководствовался когда говорил хороший:
К слову о Go. Если в Go и есть что-то хорошее, так это инструментарий. C++ по сравнению с ним – это натуральный мамонт. У C++ нет единой системы сборки, ничего даже близко похожего на единую систему управления пакетами, а еще его невероятно сложно разбирать и анализировать (это очень важно с точки зрения инструментария).
Не могу сказать что имелось ввиду хороший объективно (хотя все познается в сравнении), но как минимум хороший на фоне C++
ForestDront
19.12.2024 15:48В го плохо то, что это гуглёвское изделие. В любой момент его может запретить на территории РФ либо власть гугля, либо местная власть.
ClayRing
19.12.2024 15:48Как вы себе представляете исполнение запрета гугла на использование го на территории РФ?
JBFW
19.12.2024 15:48я представляю, но не напишу, а то кто-то подумает что ему инструкцию подогнали...
ForestDront
19.12.2024 15:48У Go свой рантайм. Гугель туда мог напихать каких угодно закладок. А это ж гугель. Неужели он удержался?
feelamee
19.12.2024 15:48ответ на ваш вопрос лежит прямо в https://github.com/golang/go
По прочтении - расскажите. Наверняка всем будет интересно узнать каких закладок напихал туда гугл
AbitLogic
19.12.2024 15:48Я потратив неделю переписал небольшой проект с Си (stm32f7) на rust с их hal, если кто смотрел HAL от stm это просто ужас, hal у Rust оказался очень простым и прозрачным, да и код проекта вышел крайне лаконичным, без этого callcxpt и прочих loopback, в итоге бинарник вместо 27Кб весит 1.4Кб, вот даже в смятение, а не пора бы прекратить мучения и в больших проектах и перейти на Rust, останавливает только слабое знание так называемой "идиоматики" Rust, всё время срываюсь и вместо функционального стиля начинаешь вложенные циклы шпарить
Sun-ami
19.12.2024 15:48Монструозность и неоптимальность - это свойства STM32 HAL, к языку C они почти не имеют отношения, а на C++ HAL может быть вообще красивым и при этом очень оптимальным, примеры этого для STM32 есть.
AbitLogic
19.12.2024 15:48Да понятно, что если мне cargo выплюнул набор инструкций их можно повторить на Си, другой вопрос какой ценой, самому лупить деструктуры, следить за памятью, замыкания, контейнеры? Тут всё инклюзив, больше думаешь над алгоритмом, а не как это всё разместить и передать... Если где-то ошибся - компилятор тебя по рукам ударит, а не выискивать потом откуда UB, откуда nullptr, почему Segmentation fault, оно же работало 5 суток подряд
По поводу HAL на C++ можно предложить достойный вариант? Мне не попадался как-то, а может и не искал, потому что и мысли не было что такое бывает, я пытался на голом STL что-то делать, он мне тупо память нафграментировал через какое-то время, не смог больше выделить кусок и я забил писать на С++ в STM
Sun-ami
19.12.2024 15:48Конкретно для stm32f7 не подскажу - то, что мне встречалось в свободном доступе, поддерживало в основном более старые контроллеры. Вообще, таких библиотек много, но все они не настолько универсальны как HAL от ST в плане поддержки всго многообразия их контроллеров. Они просто очень часто выпускают новые семейства, универсальным библиотекам угнаться за этим можно только если начинать ещё до начала их массового выпуска.
qwerty19106
19.12.2024 15:48Вот в этом и беда, что в С++ есть куча разных HAL, и нет ничего универсального. Взгляните для сравнения на embedded-hal для Rust. Если у меня проект на STM32, и вдруг понадобился WiFi, то я меняю 10 строчек кода, и 2 строки в системе сборки (Cargo.toml), и компилирую под ESP32. В С++ мне нужно переписать весь код работы с периферией.
Что мешало это сделать на С++ за ***цать лет? Да вроде ничего, язык позволяет.
Но этого нет, и вероятно уже не будет. Потому что поезд уже ушел...
Panzerschrek
19.12.2024 15:48Насколько я понимаю, желание сохранять ABI совместимость в ущерб развитию языка проистекает из практик некоторых популярных GNU/Linux дистрибутивов. Они так устроены, что там почти весь более-менее доступный пользовательский софт с открытыми исходниками собирается разработчиками системы и складывается в централизованный репозиторий. При этом для экономии места разработчики пытаются переиспользовать общие библиотеки-зависимости, чтобы несколько приложений грузили одну и ту же разделяемую библиотеку. Соответственно необходимо, чтобы ABI там совместимым был. Это касается в том числе и C++ библиотек. Но самая засада состоит в том, что в таком подходе необходима ещё и обратная совместимость компилятора, которым на пользовательской машине может собираться какой-то частный/проприетарный софт с библиотеками, которые установлены в системе (в том числе C++ библиотеками). Отсюда и требование совместимости ABI, вытекающие иногда в проблемы, что какой-нибудь std::unordered_map теперь не оптимизировать, т. к. это сломает ABI.
Решением этих пробелем мне видится изменение модели функционирования подобных дистрибутивов GNU/Linux - ближе к модели Windows, когда каждое приложение тянет с собою все зависимости и эти зависимости разработчик может собрать сам любой удобной ему версией компилятора. Стабильный ABI в таком подходе нужен только от базовых системных библиотек с голым Си интерфейсом - вроде glibc или kernel32.dll. Сборка всех зависимостей из исходников, кстати, это то, что в этой статье хвалится. Пример того, как этот подход работает, это язык Rust. Там ABI не стабилизирован и все зависимости собираются с приложением, что местами конечно не быстро, но в целом того стоит.
vadimr
19.12.2024 15:48В расте это работает, потому что компилятор один и библиотек мало.
Собрать сложное C++ приложение с внешними зависимостями из исходников – очень нетривиальная задача, и иногда и неразрешимая. О чём, кстати, пишет автор статьи.
Panzerschrek
19.12.2024 15:48Собирать всё из исходников - единственно-рабочий на долгую перспективе путь. Сам лично работал над подобными проектами, кода и внутренняя кодовая база и внешние зависимости достаточно внушительными были. Но да, подобных подход требует изначальных инвестиций времени, чтобы сборку по-грамотному организовать.
vadimr
19.12.2024 15:48В долгой перспективе часть исходников рано или поздно будет тем или иным образом утрачена. Или просто файлы потеряются, или актуальные версии сторонних библиотек разойдутся до несовместимости.
А кроме того, рано или поздно может встать задача подцепить ваши данные новой программой на другом языке.
Panzerschrek
19.12.2024 15:48Чтобы исходники потерялись надо проявить уж очень выдающиеся навыки безответственности/халатности. Обычно исходники все под контролем git или аналогов, включая централизованный репозиторий и копию у каждого разработчика. Так что такой случай можно исключить и развивать C++ дальше, жертвуя бинарной совместимостью. К тому же, если кто-то умудрился исходники потерять, то и бинарники он тоже может с той же лёгкостью утратить.
Расхождение версий библиотек при сборке их из исходников это как раз не проблема. Можно не обновлять библиотеки, если не надо, а если они обновляются, то и при необходимости пропатчить их можно. А вот при зависимости от библиотек, установленных в систему, проблема как раз и проявляется, вроде приложение на новой ОС падает, потому, что установленная там libsomestuff.so не той версии.
Чтение данных другой программой - это сколько угодно можно, если форматы стабильны, в т. ч. бинарные. Но упомянутая в статье стабильность ABI к этому отношения не имеет.vadimr
19.12.2024 15:48Стабильность ABI – это в том числе и внутреннее представление объектов.
Panzerschrek
19.12.2024 15:48Вот именно - объектов. Вроде всяких там std::unordered_map. Но в файлы их никто не пишет, их сериализуют или в текстовом формате, или в бинарном, состоящих из простых структур. А на бинарное представление структур никто не собирается покушаться.
Вообще, стандартом ни размер не внутреннее представления большинства классов стандартной библиотеки не гарантируется, как раз для того, чтобы был простор для оптимизации. Но случился ад зависимостей, как я написал ранее, и стало страшно это внутреннее представление менять.
С пользовательскими структурами же другая история. Там расположение в памяти жёстко задано и если структура грамотно составлена, то ничего сломаться не может.vadimr
19.12.2024 15:48Но в файлы их никто не пишет, их сериализуют или в текстовом формате, или в бинарном, состоящих из простых структур.
“Может, бросить всё и уехать в Урюпинск?”
Вот прямо сейчас вторую неделю сижу над расшифровкой hex-дампов сетевых пакетов одной унаследованной программы на C++. Какой-то мусор там находится в некоторых местах в векторах, не могу понять принцип его расположения.
Panzerschrek
19.12.2024 15:48Видимо да, в конкретно вашем случае кто-то поступил не хорошо, сериализуя не так, как это было бы правильно. Но я всё же не считаю правильным тормозить развитие языка из-за того, что кто-то много лет назад какую-то программу не очень хорошим образом написал.
vadimr
19.12.2024 15:48Так эти кривые программы и являются основным активом языка С++, хочется нам этого или нет.
Arlekcangp
19.12.2024 15:48Это абсолютно анти-системный подход. Если именно этот подход блокируют старые комитетчики с++ , то я за них. Потому что это приведет к еще большему раздуванию размеров приложений. А вот какой от этого выигрыш то будет? На 10% быстрее? Если нужно в каком то месте оптимизировать - так есть inline. Не надо в этом месте делать ABI call к библиотеке. Всю оптимизацию на компилятор не переложить, часть все равно должна выполнять прокладка между стулом и клавиатурой. Опять же, есть режим статической линковки - там пожалуйста, хоть какой abi делайте. Но то что является внешним api (а это то, что таковым явно объявляет та самая прокладка и то, что по факту составляет зависимость/библиотеку) должно быть и по abi стандартизировано.
Как я полагаю, в этом же и загвоздка с модулями. Могу предположить, что в их не принятии комитетом виноваты сами авторы изменений. Они хотят не оптимизировать сборку, для чего собственно модули, а протолкнуть именно новую методологию. Если верить написанному, то с моей точки зрения ущербную, т к она по сути наоборот сломает модульность, после чего какое-то время все будут плеваться, и сидеть на старых версиях стандарта, а потом просто появится конкурент плюсам уже настоящий без этих странных изменений.
e_u_g
19.12.2024 15:48Вброшу...
На мой взгляд, ещё одна существенная проблема С/С++ это синтаксис, преисполненный разными символами. Все эти *, &, ->, >>, ! и т.д.
Доводилось читать код человека, обожавшего перегружать операторы - ужасно.
Автор определяет два вида компаний, пишущих на с++. Интересно было бы узнать пропорцию. Моя догадка, что количество "молодых модных стартапов" сильно меньше "замшелых ретроградных контор". И, возможно, причина этого именно в нежелании условной молодёжи разбираться во всех оных закорючках. А было бы наоборот, первое лобби продавило бы новые стандарты и инструменты, несмотря на сопротивление второго.П.С.
А вот бы сделали нативный компилятор питона.
commanderxo
Обсуждали уже, две недели назад. Впрочем, ваша версия перевода мне нравится больше. Спасибо.