LINUX.ORG.RU

юнионы в C++

 


2

4

Пишу телегу против плюсов. В связи с этим вопрос - насколько широко в плюсах используются нуль-терминированные строки, юнионы, неумные указатели и всё такое плохое, что делает Си опасным языком.

Даже интересует не столько то, насколько они используются в существующих программах, а есть ли примеры программ, где хорошие средства плюсов сконсолидировались и поставили заслон от опасных конструкций Си, позволив полностью избежать их использования и избавиться от типичных ошибок Си. Можно ли так написать что-то существенно сложное? Сделано ли это в любимых библиотеках (Буст, QT и иже с ними)? Вторая часть вопроса - это неопределённое поведение. В Си его много. Это подаётся как фича, но с точки зрения безопасности это дыра. Меньше ли неопределённого поведения в С++?

Есть две полярные точки зрения на вопрос:

а) С++ перекрывает Си, поэтому там всё сделано по-другому, поэтому безопасность выше б) С++ - наследник Си и в целом наследует его недостатки.

Поскольку я мало пишу на Си и ещё меньше на Си++, у меня нет сложившегося мнения на эту тему. А у ЛОРа наверняка есть мнение, даже несколько.

★★★★★

Последнее исправление: xaizek (всего исправлений: 4)

Ответ на: комментарий от AntonI

Ну ты просто посмотри на начало темы - там вопрос, а не утверждение. Ну и в общем-то логика «если один нелюбитель плюсов верил в то, что американцы не могли долететь до Луны, то все нелюбители плюсов - психи» - это логика уровня Бог. Я составил своё мнение о плюсах, когда сначала ими увлёкся, потом что-то пошло не так, потом параллельно прознал про лисп. Метапрограммирование в лиспе по сравнению с метапрограммированием в С++ - это просто как Мерседес и Запорожец. Равно как и всякие штуки с динамической генерацией кода. Равно как и безопасность. После плюсов производит очень большое впечатление, когда твоя программа, которую ты всё это время дорабатываешь, работает, допустим, неделю без остановки. Далее, сравнить ООП в плюсах и ООП в лиспе, которое можно к тому же менять в любом направлени - тоже сильно не в пользу плюсов. Поэтому для приложений несравнимо комфортнее использовать лисп. Для системщины другое - общелисп далек от железа, а «лисп вообще» из-за избытка скобок не слишком удобен. Потому тут у меня нет чёткого мнения, но я системщиной и не занимался особо.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от den73

На вопрос в начале темы ответили многократно, как и на вопросы зачем и почему нужны плюсы. Но Вас эти ответы не удовлетворили, и вот тут Вы уже становитесь на один уровень с букози и ко.

Я не ровняю всех нелюбителей плюсов/миссии аполлон/круглой земли/… Но если человек, не являющийся специалистом в какой то области (неважно какой), игнорирует аргументы специалистов и продолжает настаивать на своем - вот тут уже нужно звать психологов или психиатров. В отношении букози уже давно все совершенно понятно (товарисч весьма стабильно выдерживает стиль и уровень дискуссии), теперь вот Вы пошли по его стопам… это нифига не радует;-(

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от Kroz

Мой недавний пример, правда из мира Python, но это сути дела не меняет. Есть базовый класс - список. Мне нужен точно такой же, но с небольшой дополнительной логикой. Был вариант сделать свой класс, а данные (список) поместить в переменную класса. Но тогда приходилось заново описывать все функции по работе со списком. Поэтому было проще отнаследоваться от списка и переопределить/добавить лишь пару функций

Ты начинаешь рассказ про контейнеры питона челу, который сделал вот это:
https://github.com/byko3y/python-shared-objects
Пожалуйста, не надо, я знаю, какие убогие в питоне контейнеры, и там всё упирается в то, что ты вынужден опираться на сишные функции по причине убогой производительности питоньего кода — что не имеет отношения к проблема C++, где ты можешь неограничено писать свой код такой же производительности.

Боязнь STL из-за якобы «проблем с производительностью» - в ту же корзину. Мало того, что порой это приводит к обратному эффекту - замедлению, но еще и уводит фокус программиста от логики самой программы, а также почти наверняка привнесёт новые увлекательные проблемы и побочные эффекты

Тогда возникает обратная проблема: стандартная слишком примитивна для высокого уровня. До самых недавних пор в стандартной либе не было даже понятия «экран» и «клавиатура», ты даже не мог банально сделать «Press any key...» — расскажи мне больше про «уводит от логики самой программы».

Ассоциативный массив на связанном списке или массиве с тупым перебором можно написать на любом императивном языке — вопрос лишь в производительности. Если тебя не колышет производительность, то лишними в STL оказываются: std::array, std::deque, std::forward_list, std::set, std::map, и все unordered варианты оных. То есть, почти вся либа контейнеров — они были созданы ради производительности.

Если вы пишете код для контроллеров или других устройств с ограниченными ресурсами, я бы сказал, что С++ не лучший выбор. Скорее всего нужно что-то более низкоуровневое, вроде С или Ассемблера

Или паскаля, бг-г-г.

Поэтому STL в подавляющем большинстве случаев - отличный выбор

Скорее «стандартный выбор». Есть варики не хуже STL, но все они проигрывают нестандартностью.

Если программер не умеет работать UB, то ему и в С и в С++ лучше не соваться

Полностью согласен, потому я и пишу, что C/C++ медленно, но уверенно умирает.

По поводу указателей не понял: использование стандартных контейнеров как раз и преследует цель самостоятельно не выделять/освобождать память (где это возможно), к чему тогда указатели?

К тому, что тогда у тебя каждая мелкая переменная будет в std::shared_ptr/weak_ptr, и тогда получатся значительные накладные расходы по читаемости и рантайму.

В Си у тебя почти любая функция должна возвращать два типа значений: одно - то, которое ей (функции) полагается по логике, второе - код ошибки если возникла исключительная ситуация. В Си нужно делать специальные приседания, чтобы такое реализовать

Да, и это величайший пролюб Страуструпа. Обладая отсутствием фантазии, Страуструп пошел по пути наименьшего сопротивления, передавая статус ошибки не возвратом из функции, а «глобальной переменной» — исключением, сохраняя тот же сишный дух «всегда возвращаем int из любой функции». Этот вариант, очевидно, не работает для более сложных сценариев, поскольку глобальных переменных с ростом сложности нужно две. три, четыре, ты можешь нарастить размер возвращаемого значения, но ты не можешь нарастить стэк исключений.

Чисто теоретически возможно исполнить возврат ошибок составным значением в C++, но по факту недостатки многословности такого подхода конкретно в C++ затмевают преимущества, хотя в Go, Rust, F#, Haskell это работает, поскольку там изначально продуман сахарок.

С++ решает эту проблему, потому как требует от программиста просто написать throw; даже если ты не словил исключение, ты хотя бы корректно закроешь то, что нужно корректно закрыть (если, конечно, ты следовал RAII)

И вывалишься в ту же корку? А разница? Разница возникает, когда тебе все-таки нужно в какой-то момент сделать безупречную обработку ошибок, но ты понятия не имеешь, кто, когда, и почему может бросить исключение, поскольку почти все ошибки у тебя неявны.

Да, настоятельно рекомендуется потратить 2 часа на прослушивание Exception-Safe Code часть 1 и часть 2, ну, или эквивалент

В первой же части лектор соглашается с мной в том, что работа с исключениями крайне сложна и коварна. Он привел пример фундаментального кода, который годами использовался, пока кто-то не возразил «эй, оно же некорректно обрабатывает исключения!». Как бы ты не старался корректно обрабатывать исключения, твой код неизбежно будет густо упыпан багами обработки исключений. Я 6 лет писал на делфях, и как бы я тщательно не пытался обрабатывать все ошибочные сценарии, их все равно настолько много, что где-то в каком-то сценарии глобальное состояние оказывается в некорректном состоянии, не обработанном в блоках finally/деструкторах, и из этого состояния программа уже не может выйти.

Самый главный фактор здесь — исключения увеличивают комбинаторную сложность программы. То есть, наращивают на порядки эффективно число «строк кода», логических сущностей, сценариев выполнения, не увеличивая при этом функциональности этого кода. Исключения — это отход от структурного программирования, возврат к goto лапше, к хрупкому коду, который никто не понимает, потому это абсолютное зло. И я не вижу, в каком месте лектор Jon Kalb со мной не согласен — разве что в том, что даже не смотря на всю ущербность подхода он продолжает пытаться учить им пользоваться, а не отказаться от него целиком.

byko3y ★★★★
()
Ответ на: комментарий от den73

для приложений несравнимо комфортнее использовать лисп

Зависит от приложений. У нас в HPC для некоторых задач вообще активно используется генерация плюсового кода на питоне. Я уже писал, что задачи очень разные, где то плюсы ненужны, где то без них никак. Где и почему без них никак я тоже писал.

Тот же хаскель у нас не прижился, хотя активно пробовали. Лиспом я по молодости увлекался, но не зашло. Я бы хотел что бы плюсы были заменены каким нить D/растом/…, но я до этого наверное уже не доживу, несмотря на бурное развитие ИТ. Монополии бывают очень устойчивы.

AntonI ★★★★★
()
Ответ на: комментарий от den73

Ну и в общем-то логика «если один нелюбитель плюсов верил в то, что американцы не могли долететь до Луны, то все нелюбители плюсов - психи» - это логика уровня Бог

Слава богу, я не один вижу, что мой визави — пустопорожняя балаболка, которая разбрасывается словами и намеренно искажет аргументы, и в следующий же момент делает вид, что ничего не говорил и это сама публика меня так назвала, а не он пять минут назад. Это психология «напресточника», ни одному слову которого нельзя верить, который скажет то, что ему выгодно прямо сейчас, и убежит. Тот факт, что он может показать пару работающих трюков, пусть вас не смущает — садисты тоже обычно умеют расположить к себе человека.

У меня довольно скудный опыт общения с наперсточниками, потому я сразу не распознал, что никто не обращает внимания на этот цирк и не участвует в нем, я стараюсь сам для себя — а для себя я всё и так уяснил.

Если говорить про так называемый «лунный заговор», то на самом деле с тех пор проблем в теоретической модели полета я не нашел — проблема именно в практическом исполнении. Грубо говоря, это как пять раз написать программы на сотни тысяч строк так, чтобы все пять безупречно отработали, потому что минимальная ошибка — и кровь, кишки, открытый космос. Напоминаю, что в программе Аполлон не было ни одного трупа в космосе. Не говоря уже о том, что у многих людей есть сомнения в фактических характеристиках использованной ракеты-носителя.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ну как бы я тоже с сомнением отношусь к американским космическим достижениям, об этом было много споров и все стороны приводили весомые аргументы. Я в итоге пришёл к решению «а фиг знает, были или нет, рано или поздно люди полетят на Луну и проверят». Во всяком случае, то, что они наснимали киношек, не доказывает, что они там были. Киношки они снимают умеют и без всяких полётов на Луну. Особенно меня умилила звёздная слепота астронавтов - тут уже стало понятно, что они там много подмухлевали ради понта. Но это не имеет никакого отношения к плюсам.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от AntonI

Питон - это ведь тоже хромоногий лисп. В чём-то он лучше лиспа, но лучше он во второстепенном, а уступает в более важном. Сам по себе факт, что в Qt не смогли обойтись языком, а нагенерировали своих внешних препроцессоров, уже многое говорит. Плюс реклама из серии «не пользуйтесь препроцессором, у нас есть константы» - это же явно неадекватная реклама, поскольку она не покрывает все применения препроцессора. А ведь это было написано в книжках и находились те, кто верил в эти книжки. А я же сразу увидел, что это просто пропаганда.

den73 ★★★★★
() автор топика
Ответ на: комментарий от byko3y

и в следующий же момент делает вид, что ничего не говорил

Надо ловить за язык и не переходить к следующему пункту, пока по первому факту балабольства человек не сдаст назад в явной форме. Обычно через несколько страниц флуда такие люди отступают.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Питон - это ведь тоже хромоногий лисп.

Эммм… нет. Питон это смаллток без сообщений скорее. Питон исключительно хорош в своей нише (скриптота и прототипирование), и все проблемы начинаются когда его суют куда то за пределы этой ниши. Ну и конечно слом обратной совместимости при 2to3 переходе сильно попортил крови. Основные бонусы питона - крайне низкий порог вхождения и при этом крайне высокая скорость разработки.

Насчет Qt - я под плюсами его не юзал, я только PyQt использую Логика и архитектура там конечно инопланетные, но привыкнуть можно. К счастью я редко делаю гуйню.

Qt это все же вещь в себе, я бы скорее понял претензии к STL. Но STL это первая такая шня, понятно что первый блин не очень. И главное, C++ не требует обязательного использования STL, без STL вполне можно обойтись. Как и всякий мультипарадигменный ЯП C++ позволяет писать в очень разных стилях, начиная от дикого нагромождения ООП и заканчивая этаким C с шаблонами.

AntonI ★★★★★
()
Ответ на: комментарий от den73

Ну как бы я тоже с сомнением отношусь к американским космическим достижениям

Уже есть фото их барахла на луне от независимых наблюдателей.

об этом было много споров и все стороны приводили весомые аргументы.

Аргументов от букози и ко не было, был псевдонаучный бред в стиле «этого не может быть потому что этого не может быть никогда», обвешанный физическими терминами смысла которых они сами не понимают. Для конспирологии это обычное дело, тут нужен психиатр а я все таки физик.

ПО для SpaceX разработано на С++ (комментарий) и вверх по треду, там эпично.

PS Да, плюсы тут притом что ПО для космоса сейчас пишется на плюсах в т.ч.

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от den73

Сам по себе факт, что в Qt не смогли обойтись языком, а нагенерировали своих внешних препроцессоров, уже многое говорит.

…о Qt и том времени.

https://github.com/woboq/verdigris

у нас есть константы» - это же явно неадекватная реклама, поскольку она не покрывает все применения препроцессора

Полностью работает в обратную сторону: препроцессор не покрывает все применения констант, поэтому твой комментарий – неадекватная реклама. Как, впрочем, и все остальные, и сам пост.

Siborgium ★★★★★
()
Ответ на: комментарий от byko3y

обратный порядок может оказаться неправильным

А может не оказаться.

всё приходит к тому, что ДЕСТРУКТОРЫ НЕДОПУСТИМО ВЫЗЫВАТЬ просто так, когда попало, перед этим объекты обязательно нужно развязать, финализировать, возможно даже чего-то подождать,

Разрешаю, развяжите и чего-то подождите, а потом вызывайте.

а там внезапно еще и исключения могут возникнуть, и что с ними делать?

Обрабатывать.

поскольку крестовое RAII

Другого не существует. defer это не RAII по определению, финализаторы в управляемых языках имеют все те же проблемы + неопределенность того, когда они окажутся вызваны.

поскольку крестовое RAII не способно дать достаточных гарантий безопасности

Какой безопасности?

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от archie

Высокоуровневые механизмы отличаются в первую очередь абстракциями над низкоуровневыми деталями

Рейнджи не абстрагируют низкоуровневые детали, а просто позволяют их более удобно компоновать. Еще раз, это клей.

Вот filesystem вполне абстрагирует, тут я не могу спорить.

Все это в сумме делает современный С++ более высокоуровневым языком, чем С++98, и позволяет пытаться лезть в прикладнуху

Как наличие std::optional в STL делает С++ более высокоуровневым языком? Это чисто библиотечная фича для удобства, наколеночный optional пишется за 15 минут.

Ну напиши хотя бы вот это на обычных итераторах, а еще лучше на голых указателях, может и поймешь.

Боже, ты реально думаешь, что рейнджи принципиально нельзя передавать в виде двух отдельных итераторов? Это попросту менее эргономично, и теряется возможность передавать возвращаемое значение из функции (т.к. оно одно) параметром, но принципиально это ничего не меняет.

Это чем же надо упороться, чтобы на серьзных щах сравнивать «поддержку GC» в С++11 (полоумные указатели)

Аааа, так ты и не в курсе.

https://en.cppreference.com/w/cpp/memory

Секция «Garbage collection». Также рекомендую окунуться в историю и почитать связанные с этим papers.

Siborgium ★★★★★
()
Ответ на: комментарий от archie

Напоминаю, что при наличии пакетного менеджера полностью отпадает необходимость шариться в системе и искать там нужные хедеры и либы.

Нет, это выполняет система сборки, которая – в твоей же модели – затем вызывает пакетный менеджер с нужными параметрами. Это если речь идет о «крейтах» и других подобных зависимостях.

Я сейчас говорю о стандартной библиотеке, о libc, о версиях системных хедэров – которые ты не скачаешь через пакетный менеджер. ВНЕЗАПНО, autotools выполняет configure не просто так.

Различных ОС и компиляторов не так много

А теперь помножь на разные версии компиляторов. Начиная с С++20 эта проблема чуть менее актуальна, но также необходимо выполнять тесты на наличие фич, заголовочных файлов и т.д., и генерировать макросню для совместимости.

Что самое важное, это не должна выполнять система сборки. Система сборки берет на себя рутинные задачи, но билдскрипты все равно писать нужно – потому что нельзя все включить в систему сборки.

Охрененный пример типового проекта.

Это как раз тот проект, который нужно писать на С++, а не на других языках.

В симейк файле вижу в основном настройку таргетов и их свойств

  1. nlohmann-json зачастую используется как ho-библиотека, и никаких симейков не требует
  2. она никак не взаимодействует с системой, поэтому ей это не нужно

Ты молодец, вытащил удобный пример, про подобные которому я уже писал ранее, и теперь героически победил в споре. Жму руку.

Это ты про модуль cmake-conan

meson ты предпочел проигнорировать, удобно.

императивными соплями и для каждой зависимости набивать горы копипаста из conan_cmake_configure/conan_cmake_autodetect/conan_cmake_install?

Это «набивается» один раз. Про зависимости в крестовых проектах я уже ответил.

Убогое говно, не имеющее ни автоматического разрешения зависимостей, ни соответствующей инфраструктуры для нее

Тогда не может и meson. Удобно вырывать что-то из контекста и героически оспаривать – опять.

Ибо надо какие-то мутные шкрипты сидеть писать, а не настройки мышью натыкивать.

Я еще раз спрашиваю, ты лично настройки мышкой натыкивал? XML редактировал? Никого не волнуют проблемы отдельно взятой команды. На «накликивание» мышкой настроек проекта в MSVS уходит невероятное количество времени для сколь-нибудь сложного проекта. На скрипт в CMake – гораздо меньше. Мне довелось редактировать XML’ную лапшу MSVS’ных проектов и «накликивать», и немало – и я не желаю этим заниматься никогда больше.

Siborgium ★★★★★
()
Ответ на: комментарий от den73

А вот ещё интересная табличка, которая показывает, что в полном Дебиане со всеми пакетами С++ менее чем вдвое уступает C по количеству строк, а когда-то разрыв был на порядок.
https://sources.debian.org/stats/#hist_sloc

Я так понимаю, что эти нечитаемые графики строила софтина на Си. Картина нерепрезентативна, мягко выражаясь, поскольку никсы изначально были вендоролоком на Си, где до сих пор нет самостоятельной клиентской либы для юзерспейса, вместо которой используется стандартная библиотека Си.

byko3y ★★★★
()
Ответ на: комментарий от Crocodoom

ведут два чувака с околонулевым практическим опытом в C++, зато с крайне широким теоретическим «кругозором», где языки тесно переплетаются с масонами, госдепом США и мировыми заговорами

Про околонулевой ты загнул. Уже несколько месяцев пишу на крестах за деньги, до этого годами потыкивал изредка и пару месяцев активно изучал.

byko3y ★★★★
()
Ответ на: комментарий от den73

Отрицать наличие того, что закладки вставляются системно и целенаправленно - это даже хуже, чем быть психом. Man Crypto AG

Пф-ф-ф, на КАЖДОМ современном десктопе стоит неотключаемый бэкдор. Man Intel ME. Man AMD PSP. Особенно забавляет «The Intel Management Engine always runs as long as the motherboard is receiving power, even when the computer is turned off».

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от alysnix

там чужие строковые константы что ли? в том и фишка, что в плюсах можно делать классы, что выглядят как встроенные типы

Очень сомнительный аргумент, прежде всего потому, что «встроенные типы» в Си весьма убоги, так что от словосочетания «выглядеть как встроенные типы» не веет позитивом. И еще менее веет позитивом от модификаторов типов const и volatile — volatile уже активно убирают из крестов, а вот const почему-то задержался. Они плохо работали даже в Си, но на сложных структурах данных в крестах они работают просто отвратительно.

byko3y ★★★★
()
Ответ на: комментарий от ox55ff

Значит этот объект не должен быть константным

В точку! Именно это я и предлагаю делать.

void print(const std::vector<int>& items) {

Проблема твоего примера в том, что это массив примитивных значений. Если ты возьмешь массив хотя бы std::string, то отхлебнешь горя сполна, обрабатывая const std::vector<const std::string>& , также известный как const std::vector<std::string>& , std::vector<const std::string>& , и std::vector<std::string>&.

byko3y ★★★★
()
Ответ на: комментарий от ox55ff

Потеряем ибо будет возможность случайно изменить объект, когда это не предполагается. Например я пишу код параллельной обработки массива и хочу дать множеству потоков доступ к объекту, который хранит некоторые данные, необходимые для расчётов.
Если я потокам передам этот объект в виде ссылки на константный объект, то это явно укажет, что изменение запрещено, разрешено только чтение. А при попытке изменения будет ошибка компиляции

Я отвечал DarkEld3r-у развернуто о том, почему на самом деле это не работает. Фундаментальная причина провала const в C/C++ заключается в том, что в них принято использовать модифицируемые ссылки и кастовать модификатор const на указателях, из-за чего у тебя константный объект может неожиданно измениться внутри функции, которая этого не ожидает, или после добавления константного значения в вектор внезапно получится, что этот модификатор потеряется, поскольку в другом месте держится ссылка на вектор неконстантных значений (в самом весёлом случае компилятор вставит неявное копирование вектора). Из-за этого оптимизирующие компиляторы по факту игнорируют модификатор const при компиляции, а крестовая ссылка «&» ими интерпретируется так же, как указатель «*».

Выход примерно такой же, как это сделано в STL с const_iterator, ограничивающими возможные действия, только без применения модификаторов «const».

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Очень сомнительный аргумент, прежде всего потому, что «встроенные типы» в Си весьма убоги, так что от словосочетания «выглядеть как встроенные типы» не веет позитивом.

предложи «неубогую» систему встроенных типов. ты вообще кто? «два месяца на с++ за деньги» - этим все сказано.

я вот 20 лет «на с++ за деньги» и до сих пор волосы шевелятся от новых его стандартов.

alysnix ★★★
()
Ответ на: комментарий от byko3y

Про околонулевой ты загнул. Уже несколько месяцев пишу на крестах за деньги, до этого годами потыкивал изредка и пару месяцев активно изучал

Это и есть околонулевой в масштабе опыта твоих оппонентов. Смотри, я пишу на крестах за деньги уже несколько лет - буквально на порядок дольше твоих «нескольких месяцев» («тыканье» не в счёт) А тут есть люди, которые пишут на C++ ещё с прошлого века - наберётся на ещё один порядок.

Конечно, культа из «седых мудей» делать не надо, это другая крайность... Писькомерки годами стажа, равно как и зарплатой (это к «поршику» в соседней теме) - я не к этому призываю, если что. Просто обрисовываю контекст

Такие темы, как ваши, очень полезны с дидактической точки зрения 🙂

Crocodoom ★★★★★
()
Последнее исправление: Crocodoom (всего исправлений: 1)
Ответ на: комментарий от ox55ff

Зачем ты вместо std::string взял basic_string с явным указанием шаблонных параметров? Они там отличаются от дефолтных.
Их там много, потому что хотели строчку сделать универсальной и настраиваемой, а не потому что проще никак нельзя. Можно

Первый пример, который под руку попал. Мой аргумент был к тому, что люди хотят простой идентификатор составного типа со сложными кишками. Но если ты на всю это сложность вешаешь единственный бинарный ярлык «const/non-const», то это совершенно не соответствует реально требуемым ограничениям доступа, которые более разнообразны, сложны, и тонки.

Например, очень часто требуется сделать подсчет ссылок для константных объектов. Тогда либо ты делаешь интрузивный счетчик без оверхеда и лепишь coonst_cast во все методы, либо с оверхедом рантайма и читаемости через shared_ptr, но вот беда: std::shared_ptr<const std::string> и std::shared_ptr<std::string> — это два несовместимых типа, а хотелось бы передавать константы и неконстанты в те же функции.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Например, очень часто требуется сделать подсчет ссылок для константных объектов.

константность сообщает компилятору что, например, значения полей объекта размещенные например в регистрах (для эффективности) не меняются, если вызывался констатный метод. и их можно не перегружать из обьекта заново. получается значительно более эффективный код. то есть константность активно учитывается при кодогенерации. констатность также учитывается при размещении обьектов в рид онли областях памяти например.

а зачем в констатный обьект внедрять неконстатный счетчик и потом пытаться об..бать компилятор, и как вообще такой обьект поместится в ROM… это непонятно.

хотите считать ссылки константному обьекту - делайте отдельный счетчик и не ипите системе мозги.

alysnix ★★★
()
Ответ на: комментарий от glebiao

Си и его наследники разрабатывались из практических соображений. Почему, собственно, быстро стали популярными

Не совсем корректно. Прежде всего Си стал популярен благодаря юниксу, который был простой примитивной недо-ОС, написанной на недо-ЯП, просто, быстро, грязно, на скорую руку, но именно эта простота позволила быстро портировать код на другие платформы, плюс сорцы доступны, потому их копировали налево и направо, создавая горы клонов, из самых популярных: чпукс, аикс, сан, system V, BSD. И потом уже никсы в себе пронесли вирус Си, поскольку стандартная либа Си была единственной возможностью дергать системные вызовы никсов.

Например, предок MS DOS был написан не на Си, а на PL/M — казалось бы, еще один практичный язык, но почему-то стал популярен именно Си. Я как бы о чем... многие решения в Си не связаны ни с какой практичностью — это просто просчеты из-за отсутствия у языка архитектуры, его просто слепили как попало: «я его слепила из того, что было, а потом что было — то и полюбила». Я здесь штатно оправдываю K&R, поскольку они никогда не предполагали, что этим языком кто-то будет серьезно пользоваться, они просто сделали препроцессор для асма, чтобы быстрее делать «херак-херак и в продакшен». Да-да, мало кто помнит, что вообще-то первый Си не был компилятором, он выдавал на выходе асмовые сорцы.

Да, если ты пишешь на Си работу с железками, то тебе нужны объединения, поскольку в Си больше ничего нет. Но в C++ есть много других фич, хотя бы tagged union.

byko3y ★★★★
()
Ответ на: комментарий от Crocodoom

Писькомерки годами стажа, равно как и зарплатой (это к «поршику» в соседней теме) - я не к этому призываю, если что. Просто обрисовываю контекст

Чувак с поршиком один из лучших программистов которых я знаю (он мне тут немножко помогал по паре задач). Точнее до некоторых пор я вообще не представлял, что можно программировать на таком уровне…

Это к вопросу о контексте:-)

AntonI ★★★★★
()
Ответ на: комментарий от byko3y

в них принято использовать модифицируемые ссылки и кастовать модификатор const на указателях

Не принято. Если нужно const_cast’ом снимать константность, то это говнокод и нужно переделывать архитектуру.

из-за чего у тебя константный объект может неожиданно измениться внутри функции

Что значит внезапно? Из другого потока? Ну так это речь уже про синхронизацию доступа.

крестовая ссылка «&» ими интерпретируется так же, как указатель «*»

Так и надо. Ссылка это указатель с дополнительными гарантиями.

Пока не понял в чём проблема. const создан для облегчения жизни программиста, а не для чего-то ещё.

ox55ff ★★★★★
()
Ответ на: комментарий от byko3y

люди хотят простой идентификатор составного типа со сложными кишками

using SimpleType = std::map<std::string, std::vector<std::string>>;

часто требуется сделать подсчет ссылок для константных объектов
лепишь coonst_cast во все методы

Это всё от незнания языка. Есть же mutable для этого.

class Foo {
int a {0};
mutable int b {0};

void setValue(int value) const { // константный метод
   a = value; // error
   b = value; // ok
}

};
ox55ff ★★★★★
()
Ответ на: комментарий от alysnix

константность сообщает компилятору что, например, значения полей объекта размещенные например в регистрах (для эффективности) не меняются, если вызывался констатный метод. и их можно не перегружать из обьекта заново

Не в c++. Потому что можно снять const и изменить значение.

То про что ты пишешь называется strict aliasing.

ox55ff ★★★★★
()
Ответ на: комментарий от Siborgium

ВНЕЗАПНО, autotools выполняет configure не просто так.

Ещё как просто так. Autotools – это одни из самых лютых костылей кгда либо сделанные программистами и их надо поскорее закопать. Также это следствие бардака с интерфейсами пакетов.

Этот configure может выполняться дольше чем сама компиляция.

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от AntonI

Чувак с поршиком один из лучших программистов которых я знаю (он мне тут немножко помогал по паре задач). Точнее до некоторых пор я вообще не представлял, что можно программировать на таком уровне…

«Чувак с поршиком» лукавит, как я и подозревал, но не имел пруфов:

Структура данных для хранения коэффициентов многомерного полинома? (комментарий)

Но денег нет! Во всяком случае пока;-)

Не в них счастье, поверьте. Завтра отпишусь

То есть, это была попытка аргументации через «я сказал, потому что у меня поршик».

По теме того треда — никакого «программировать на таком уровне» я не вижу, зато вижу «чел мне помог — он луччий, пока мне помогает». С другой стороны, нужно понимать, что это я, а меня сложно удивить, у меня даже лучшие инженер-архитекторы из гула вызывают реакцию «норм, неплохо поработали»... потому что архитекторы из фейсбука и амазона вызывают реакцию «в каком бомжатнике их откопали?».

byko3y ★★★★
()
Ответ на: комментарий от ox55ff

Не принято. Если нужно const_cast’ом снимать константность, то это говнокод и нужно переделывать архитектуру

А ты, я так понимаю, по два раза на месяц переписываешь архитектуру? Время нынче такое, что у клиента по два раза в месяц меняются хотелки, и если твои инструменты не позволяют к этим хотелкам адаптироваться, то они не нужны. О чем я и пишу весь тхреад. Это в том числе причина, почему класс-ориентированное программирование, которое публика зовет ООП, не работает — потому что два раза в месяц нужно переписывать иерархию.

Что значит внезапно? Из другого потока? Ну так это речь уже про синхронизацию доступа

Вызовет метод, который вызовет другой метод, третий... это неизбежно по мере роста сложности кода. А вызывающий код будет по прежнему думать «ну у меня же константный объект, я ево не меняю, значит я могу расчитывать на его константность» — а нет, не можешь. То есть, змея кусает себя за хвост, поток сам себе становится вторым потоком. Это один из самых сложных классов багов, поскольку его, как правило, нельзя тригернуть выполнением по частям, баг можно отловить только выполняя прогу на максимальной сложности алгоритмов.

Пока не понял в чём проблема. const создан для облегчения жизни программиста, а не для чего-то ещё

const в крестах не «создан», а высран комитетом ANSI, выдавшим одинаково бесполезные стандарты C, C++, и SQL, о неадекватности которых можно писать докторские диссертации. В книге K&R за 1978 год никаких const нету.

byko3y ★★★★
()
Ответ на: комментарий от kvpfs

Брехня, скорее всего вытекает из твоего патологического неприятия наследования, в итоге выходит циклический говнокод, почти всегда такое можно развязать. Лишь однажды заюзал shared_ptr + weak_ptr в подобном случае

У меня иногда возникает впечатление, что крестовики, с которыми я общаюсь, пишут какие-то другие программы... и на другом языке, нежели я. Потому что у меня в дереве родитель знает про дочерние элементы и дочерние элементы знают про родителя — кольцевая ссылка, однако. В каком-нибудь Qt кольцевые ссылки вообще являются нормой, там даже не просто родительский-дочерний элементы, там всё связано со всем через какие-нибудь события. Какое там у тебя «однажды» было? Сколько hello world-ов за свою карьеру написал?

struct Q {
Q(int *error_code) {

Уже придумал, как сделать в таком духе конструктор копирования-перемещения? Потому что иначе этот метод с таким же успехом может быть статичным методом с любым именем, или даже свободной функцией, возвращающей Q.

Про твоё неумение в исключения - не буду, у тебя там что-то вроде религиозных убеждений, бесполезно, однажды ввязывался

Выше постили ссылку на лекцию — никто не умеет в исключения. Об этом и речь.

byko3y ★★★★
()
Ответ на: комментарий от den73

Питон - это ведь тоже хромоногий лисп. В чём-то он лучше лиспа, но лучше он во второстепенном, а уступает в более важном

Я в питон «как бы невзначай» добавлял новые синтаксические конструкции:
https://github.com/byko3y/python-shared-objects

Да, он изначально был крайне бездарно спроектирован, эдакий «интерпретируемый Си с динамическими массивами» (то есть, не был спроектирован). Но даже с такими изъянами питон убил лисп. тот самый лисп, который был №1 ЯП с динамическими типами в индустрии своего времени. Потому что на самом деле метапрограммирование переоценено, а возможность реализовать его в питоне по крайней мере имеется.

Плюс реклама из серии «не пользуйтесь препроцессором, у нас есть константы» - это же явно неадекватная реклама, поскольку она не покрывает все применения препроцессора

К сожалению, я выступаю за то, что слишком мощное метапрограммирование отрицательно влияет на качество кода. Это актуально и для лиспа, и для крестовых либ на шаблонах, и для сложных сишных макросов. Потому что получается write-only код, для понимания которого новому человеку нужны МЕСЯЦЫ.

Сам по себе факт, что в Qt не смогли обойтись языком, а нагенерировали своих внешних препроцессоров, уже многое говорит

Говорит о том, что в C++ как раз возможности сделать DSL на базе C++ нету. Когда ты лепишь один слой костылей/совместимости поверх другого, поверх третьего, четвертого, то получается C++, то есть, язык, синтаксический разбор которого невозможно реализовать без анализа семантики. У питона, напротив, есть штатный парсер в AST, которым можно оперировать, и потом модифицированный AST скармливать интерпретатору. Я уверен, что законодатели C++ давно хотят создать что-то еще более сложное и запутанное, но имеющаяся спецификация имеет просто неподъемную сложность, выше которой идти уже не получается.

byko3y ★★★★
()
Ответ на: комментарий от ox55ff

using SimpleType = std::map<std::string, std::vector<std::string>>

А у меня во второй переменной есть std::map<std::string, std::vector<const std::string>> — мне с ним что делать?

Это всё от незнания языка. Есть же mutable для этого

Маленький костыль для того, чтобы отсрочить неотвратимое еще ненадолго. Поскольку неизбежно возникнет потребность в каком-то методе запрещать изменение mutable переменных, а в другом методе изменять non-mutable, которая не изменяется больше нигде.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Я читаю твои сообщения и у меня создаётся впечатление, что ты пытаешь на c++ натянуть подходы к проектированию и программированию из других языков. И из-за этого все проблемы. На c++ нужно писать как здесь принято, тогда не будет проблем. Да, придётся подучить язык и выучить принятые подходы. С наскока в c++ не перепрыгнуть.

А ты, я так понимаю, по два раза на месяц переписываешь архитектуру?

Нет. С опытом приходит умение делать архитектуру, которую, в случае необходимости, можно легко подкорректировать. Просто чувствуешь, как в конкретном случае сделать лучше. Вот ты несколько раз перепишешь свой код и тоже научишься. Только нужно принять c++ каким он есть, а не пытаться тянуть подходы из других языков.

потому что два раза в месяц нужно переписывать иерархию

Значит плохая иерархия.

Вызовет метод, который вызовет другой метод, третий…

Если в первый метод передать const, то он дальше в другие методы по цепочке тоже const будет передавать и никто не сможет изменить. А если ты делаешь параллельные потоки передачи ссылок (const, не const), а потом огребаешь проблемы, то ССЗБ. Опять проблема в архитектуре, а не в языке.

не «создан», а высран

Да нормально всё с const. Просто ты не понимаешь его предназначения и требуешь чего-то сверх.

ox55ff ★★★★★
()
Ответ на: комментарий от byko3y

std::vector<const std::string>
const

Зачем? Без const делай. Если нужна неизменяемость, то делай константным весь map.

Маленький костыль для того, чтобы отсрочить неотвратимое еще ненадолго.

Ты захотел счётчик. Я тебе показал как: пометь переменную счётчика словом mutable и изменяй её в константных методах. mutable как раз для таких редких случаев и создан. Ещё мьютексы им можно помечать, если константные методы требуют синхронизацию в многопоточном коде при доступе к полям класса. Но злоупотреблять не стоит. Если требуется много mutable, то… да, да, неправильная архитектура.

Поскольку неизбежно возникнет

Не согласен про неизбежность. Из личного опыта. Семь лет на крестах пишу без учёта универа.

ox55ff ★★★★★
()
Последнее исправление: ox55ff (всего исправлений: 1)
Ответ на: комментарий от byko3y

Интелу ME далеко до Crypto AG. Очень далеко. И как раз IME - это следствие феерического успеха с Crypto AG. США попробовали бекдоры, у них прекрасно получилось. Их поймали на жульничестве, но никто не потребовал вернуть назад деньги за все битые шифрмашинки. Равно как все не отказались покупать процессоры с IME, а расхватывали их как горячие пирожки. Как говорится, если ты меня обманул один раз - то ты плохой. Если ты меня обманул два раза - то я плохой.

Что изменилось со времени Crypto AG.

  • элементная база
  • объём работ, возлагаемых на машинки

Невозможно придумать ни одного мотива отказаться от переноса успешной практики на новую почву.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от Siborgium

Полностью работает в обратную сторону: препроцессор не покрывает все применения констант, поэтому твой комментарий – неадекватная реклама.

Оно в обе стороны работает. В твоих файлах на C++ нет директив #include и #ifdef? Где в моём комментарии неадекватная реклама? Что именно я рекламирую? Написать «сам дурак» конечно проще всего, но иногда перед этим стоит подумать.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от AntonI

Почему вопросительный знак? Ты не уверен, на чём я настаиваю?

den73 ★★★★★
() автор топика
Ответ на: комментарий от Siborgium

Аааа, так ты и не в курсе. https://en.cppreference.com/w/cpp/memory Секция «Garbage collection». Также рекомендую окунуться в историю и почитать связанные с этим papers.

Открыл, мне же интересно. Читаю:

Garbage collector support

declare_reachable
  
(C++11)(removed in C++23)

Что-то пошло не так?

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от byko3y

К сожалению, я выступаю за то, что слишком мощное метапрограммирование отрицательно влияет на качество кода.

Да. Но слишком слабое - тоже.

Говорит о том, что в C++ как раз возможности сделать DSL на базе C++ нету.

Именно!

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

removed in C++23

Ну и хорошо. Было бы не пришей кобыле хвост. Помню нытьё с неосиляторством std::async. Что было бы со сборщиком мусора представить страшно. Уберегли c++ от непоправимого.

ox55ff ★★★★★
()
Ответ на: комментарий от byko3y

Потому что у меня в дереве родитель знает про дочерние элементы и дочерние элементы знают про родителя — кольцевая ссылка, однако.

Они у тебя не просто знают друг о друге, ты толкуешь о каком-то сложном деструкторе, который там чего-то сложного делает, это уже странно. Ты ведь мог сделать метод deinit(), который дёрнул бы у всех объектов, а потом уже звать тривиальный деструктор. В общем проблему ты из пальца высосал.

Потому что у меня в дереве родитель знает про дочерние элементы и дочерние элементы знают про родителя — кольцевая ссылка, однако.

Ну и кто тебе сказал, что у тебя там нормальная архитектура? Почему ты не передаёшь объекты через параметры методов лишь в контекст конкретной функции? Пишешь лютое Г, а потом экстраполируешь на всех.

Уже придумал, как сделать в таком духе конструктор копирования-перемещения?

Когда дойдёшь до потоков ввода/вывода, обрати внимание на методы good()/eof()/fail() …

Выше постили ссылку на лекцию — никто не умеет в исключения. Об этом и речь.

Я не буду в это втягиваться, и лекцию читать не стану. Ремарка, чтобы не возникло ощущение, что я согласился.

kvpfs ★★
()
Ответ на: комментарий от byko3y

Выше постили ссылку на лекцию — никто не умеет в исключения.

Jon Kalb что-ли? Это только основы, которые должен каждый знать.

rupert ★★★★★
()
Ответ на: комментарий от den73

В твоих файлах на C++ нет директив #include и #ifdef

Я где-то написал, что препроцессор не нужен? Цитату мне бегом.

Где в моём комментарии неадекватная реклама? Что именно я рекламирую?

Использование препроцессора вместо других, более совершенных средств, которыми можно заместить ряд применений препроцессора.

Siborgium ★★★★★
()
Ответ на: комментарий от byko3y

Но даже с такими изъянами питон убил лисп. тот самый лисп, который был №1 ЯП с динамическими типами в индустрии своего времени. Потому что на самом деле метапрограммирование переоценено, а возможность реализовать его в питоне по крайней мере имеется.

Шизофазия.

Разложу твое же сообщение по тезисам:

Лисп и питон являются языком с динамическими типами.

Метапрограммирование переоценено.

В питоне возможности метапрограммирования меньше, чем в лиспе.

Питон убил лисп.

Как все это связано – неясно.

Говорит о том, что в C++ как раз возможности сделать DSL на базе C++ нету.

Говорит о том, что @den73 не знает ни языка, ни библиотек. Показательно читать такое сразу после

по итогу ты открываешь код и такой «это кресты?», потому что ты никогда в жизни не видел такого синтаксиса… а он есть, компилируется и выполняется.

Когда @byko3y видит DSL и не понимает синтаксис – это не проблема @byko3y, это проблема С++. Когда @byko3y, не зная языка, не понимает, что на С++ можно, а что нельзя – это тоже проблема С++.

синтаксический разбор которого невозможно реализовать без анализа семантики

Не имеет значения.

Siborgium ★★★★★
()

Пишу телегу против плюсов.

Для НПО «Эшелон»? Неужели у вас ни одного эксперта по C++ не нашлось?

rupert ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.