LINUX.ORG.RU

юнионы в C++

 


2

4

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

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

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

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

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

★★★★★

Последнее исправление: xaizek (всего исправлений: 4)
Ответ на: комментарий от kvpfs

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

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

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

Достаточно соседних элементов элемента для вставки или удаления. Вполне можно сейчас нафантазировать всяких случаев, что-то будет норм, конечно, но большинство - из-за кривой архитектуры. Но даже все эти взаимные ссылки не критичны, byko3y же решил клепать сложные деструкторы с какими-то сложными действиями по всей объектной композиции (ссылаясь на уже мертвые объекты), это явно говорит о качестве проектирования, чего он не признает, ведь виновато RAII.

PS: из последнего, где бы я оставлял ссылку на что-то внешнее для хранения в объекте - итератор для самопальной юникодной строки. Но всё это скорее исключения, в норме надо этого избегать (это не про шаред птр, а про простые ссылки). Ну а делать с такой ссылкой что-то в деструкторе - …

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

Примерно в это время я знакомился с C++ и пришел к однозначному выводу, что на этом дерьмищи нельзя написать ничего работоспособного.

Уже несколько месяцев пишу на крестах за деньги

Я правильно понял, что вам уже несколько месяцев платят за то, что вы пишете неработоспособный код?

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

Не совсем корректно. Прежде всего Си стал популярен благодаря юниксу, который был простой примитивной недо-ОС

Угу. Если делаете исторические реминисценции, историю надо знать. Начиная с истории юникса, который, всё-таки, был не «недо – ос», а простой, но первой полноценной и практичной (то бишь, НЕ Монитором) переносимой операционной средой для мини и микро компьютеров. Других, тупо не было! «Полноценные» ОС, как легко увидеть из литературы, либо были дорогущим долгостроем, либо имели жёсткую привязку к конкретному железу. Соответственно, наработанного под «полноценные ОС» системного и прикладного софта попросту было… скажем так, мало.

И популярность Си была вызвана, всё-таки, не столько юниксом, сколько моделью и практичностью. Модель: да, моделировался под модель DEC, но в самом общем виде, без плотных привязок. Практичность: доступ (в разумных объёмах, не ломающих переносимость) к низкоуровневым штучкам, что в то время было суперкритично. Поэтому и в народ пошёл. И позднее вытеснил (более, чем популярные в то время) варианты Паскаля и бодро вытеснял Фортран.

Например, предок MS DOS был написан не на Си, а на PL/M — казалось бы, еще один практичный язык, но почему-то стал популярен именно Си.

Опять несколько мимо. Си – переносимый. Не знаю, задумывался ли он изначально, как переносимый, но жизнь заставила. PL/M — конкретно для 8008 и позднее — PL/M-80, для 8080/Z80. Сравнивать их как-то неловко. Язык (на конец 70-ых), уже имеющий зачатки развитых типов данных, структуры и т.п. и язык, с двумя типами — BYTE и ADDRESS, как-то неловко. Ну да, расширение PL/M-86 с плавучкой и расширениями правил — ок, но это уже середина – конец 80-ых. Но в любом случае, привязка к конкретному процессору…

У нас в Томске, в 80-ых, был в Политехе крайне интересный мужик. Встречался с ним всего пару раз в 86-ом, но до сих пор под впечатлением. Кажется, Гурин по фамилии. Если не ошибаюсь, он позднее работал в знаменитом проекте «2+Ку» Захарова.

Так вот, в 83 или около того, он сделал ассемблер для Д3-28 с синтаксисом, максимально приближенным к обычной алгоритмической записи. Никаким тебе mov, jb — обычные =, if и т.п. Но это был именно ассемблер. Умный, да. Удобный. Но Ассемблер, а не ЯВУ. Вот PL/M — язык точно такого-же класса и не более.

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

Да ну? Битовые поля, структуры, возможность вкладывать структуры в объединения и наоборот — столько раз, сколько нужно… Без этого, работать с аппаратурой, весьма кисло. Хотя конечно, при работе с «окошечками или картинками», это всё «опасное лишнее», да. Ну так это вопрос правильного использования инструмента, не так ли?

Но в C++ есть много других фич, хотя бы tagged union.

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

Вот в D пришла авторам блажь перенести битовые поля на уровень библиотеки. Кому-то стало от этого хорошо? Ну-ну. Лучшее — враг хорошего…

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

В мемориз… Надо все таки ввести на Лоре суперлайки.

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

Достаточно соседних элементов элемента для вставки или удаления.

1.если список с мьютексом и/или со счетчиком, то соседних недостаточно.

  1. если идет разговор о циклических ссылках, то как раз знание соседей и есть циклическая ссылка.

  2. неестественно знать каких-то 2 «соседей в группе», вместо знания самой группы. зная группу вы можете сделать выводы о роли или состоянии данного элемента. например какой-то неактивный элемент будет находиться в группе «неактивные». Ожидающий ресурса X будет находиться в группе ожидающих этого ресурса… и так далее.

я не говорю что это нужно всегда. Но есть такие ситуации, когда можно только так.

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

бегом

А чё ты занервничал-то? Понял, что попался, да?

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

Я к этому призывал? Где именно?

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

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

Возможно есть дополнительные гарантии, которые есть, например, у стандартной библиотеки, которые запрещают использовать mutable, по крайней мере без синхронизации…

https://eel.is/c++draft/res.on.data.races

Update: А, вижу ты уже дальше упомянул.

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

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

Вот не надо сравнивать базовый инструментарий, которому уже под сорокет с новациями, которым ещё и десяти не исполнилось.

tagged union, под названием variant record бы еще в modula-2, аж в 1979. итого фиче - 43 годика. но на самом деле, сишный чистый юнион, лучше чем tagged. из обычного union tagged делается просто. но не наоборот.

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

А чё ты занервничал-то? Понял, что попался, да?

То есть, цитаты не будет?

Я к этому призывал? Где именно?

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

Сейчас, конечно, будет съезд на «ну это пропаганда, ну это неадекватная реклама, но я не против». Жду с нетерпением.

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

А как при мутабельном чистом юнионе избежать ошибок, когда в одном варианте указатель, а в другом на этом же месте целое число?

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

То есть, цитаты не будет?

Я тебя первый спросил, а ты написал что-то иррелевантное. Ответь сначала на мой вопрос, потом я отвечу на твой.

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

А как при мутабельном чистом юнионе избежать ошибок, когда в одном варианте указатель, а в другом на этом же месте целое число?

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

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

Нет, я спросил первым:

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

До этого ты также проигнорировал мой вопрос, предпочтя ответить на него вопросом:

Какое отношение намеренное создание закладок имеет к ЯП?

Может быть имеет, а может быть и не имеет. Какое твоё мнение:

Прекрати позориться.


На неудобные части сообщения, видимо, решил не отвечать. Верной дорогой идешь.

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

tagged union, под названием variant record бы еще в modula-2, аж в 1979. итого фиче - 43 годика

имелось в виду появление в С и С++ соотв. Нечестное сравнение.

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

А как при мутабельном чистом юнионе избежать ошибок, когда в одном варианте указатель, а в другом на этом же месте целое число?

включать мозги и принципиально не писать в высшей степени сомнительного кода?

по крайней мере помнить, что при использовании объединений работаешь, фактически, с голой памятью, как в ассемблере, и вести себя соответственно?

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

помнить, что при использовании объединений работаешь, фактически, с голой памятью, как в ассемблере, и вести себя соответственно?

Ну вы бы это, выбирали бы выражения.

А то ведь так можно договориться и до того, что на C++ можно корректно работающий код написать.

Такого потрясения основ мироздания den73 может и не выдержать, а byko3y превзойдет по длине истеричных портянок откровения от самого Царя.

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

включать мозги

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

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

И как этот ручной тег типа защитит от ошибок? Компилятор-то про него ничего не знает.

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

Я дал ответ на этот вопрос:

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

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


Прекрати клоунаду.

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

Опять лжёшь. Я описывал как неадекватную рекламу общее пожелание отказаться от препроцессора. Потому что определение констант - это только один частный случай применения препроцессора, а отказаться рекомендуют от препроцессора целиком, невзирая на невыполнимость этого пожелания и невзирая на то, что в промышленном коде препроцессор используется очень интенсивно. Вот пример такой рекламы:

https://qbik.club/post_1281.html - и внутри ссылка на Хабр. Вот ещё: https://www.cyberforum.ru/cpp-beginners/thread1202880.html

Здесь приведены случаи, когда надо отказаться от препроцессора, но не приведены случаи, когда им нужно пользоваться. В итоге неофит начинает упарываться и пытаться отказаться от препроцессора там, где он действительно нужен.

В общем, поскольку ты мне приписываешь то, что я не делал, на твой вопрос я отвечать не буду.

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

Канонический пример задачи, которая не решается без сборки мусора - это интерпретатор лисп с возможностью удалять определения. Символы ссылаются на функции и значения, а функции - на символы, функции и значения. А значения - друг на друга. Ссылаются они так, как захочет пользователь. Вместо лиспа можно взять любой язык со ссылочными типами данных. В задаче линковки обычной программы на Си, думаю, тоже нужна сборка мусора над объектами, подлежащими линковке, чтобы выкинуть неиспользуемые объекты. Хотя это не «сборка мусора, встроенная в язык», а «алгоритм сборки мусора, применённый к конкретным структурам данных», т.е. её можно реализовать на любом языке. Ещё один вариант применения сборки мусора - это версионные СУБД, например, Postgresql и Firebird (про Оракл меньше уверен, они там грубо себя ведут и состаривают данные принудительно, вроде у них могут из-за этого возникать «висячие указатели» на уже забытые данные, не доходят руки освежить знания).

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

Опять лжёшь. Я описывал как неадекватную рекламу общее пожелание отказаться от препроцессора

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

Тем не менее, свести его использование к почти полностью исключительно #include/#ifdef – можно и нужно.

В итоге неофит начинает упарываться и пытаться отказаться от препроцессора там, где он действительно нужен.

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

В общем, поскольку ты мне приписываешь то, что я не делал, на твой вопрос я отвечать не буду.

Так бы сразу и сказал, я бы время не тратил. В игнор.

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

Если покинешь тему и перестанешь её замусоривать - только спасибо скажу.

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

ручной tagged union:

struct TUnion {
  enum {is_int, is_double } _tag = is_int;
  union{
    int _int;
    double _double;
  }
}

запись - пишется значение данного типа и выставляется тег типа.

lu._int = 100; 
lu._tag = is_int;

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

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

Если я это проверю, то да, всё будет норм. А если нет, то будет CVE. Плюс к тому, если данные мутабельны, то нужно отследить все алиасы и проверить, что нет состояния гонки между читателями и писателями. Это уже Задача.

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

Мозги есть у всех, но ошибки тоже делают все. Так что это не ответ.

Ответ.

Опасное средство? – да.

Необходимое – тоже да.

Требует повышенной внимательности и тщательного выбора — а нужно ли применять именно это средство и именно здесь и сейчас — да.

точно так же, как выбирать — стоить ли лезть в необесточенный электрощиток: временами просто некуда деться. Цена ошибки — соответственная.

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

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

Спич ровно о том, что каждому инструменту — своё (разумное) место.

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

Если я это проверю, то да, всё будет норм. А если нет, то будет CVE.

аналогично для олперации вида a/b. если так - то норм. а если наоборот.. то не норм, и даже деление на ноль например.

а если a,b еще из разных тредов устанавливаются, то будут и гонки, если код кривой… так мы доказали, что операция деления - потенциально опасна.

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

Необходимое – тоже да.

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

Нельзя: выточить голыми руками из стального прутка какой-нибудь шкив теоретически возможно (наверное)

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

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

Конечно, деление потенциально опасно. В Расте вроде даже есть специальный атрибут «число, не равное нулю», который, если его применить, компилятор проверит и не даст программисту написать код, который может поделить на ноль. Кроме этого, деление плавающих может дать результат вне представимого диапазона. И что?

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

Кроме этого, деление плавающих может дать результат вне представимого диапазона. И что?

и то, что праксисски любая операция вида F(a,b) опасна своими неожиданностями в виде гонок, неверного порядка или еще ченить.

ручной юнион опасен теми же опасностями что оператор if, поскольку чтение там таким оператором и является.

if(_tag == tag_int) {
  return _int;
}
else {
  some_error();
}
alysnix ★★★
()
Ответ на: комментарий от Siborgium

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

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

STL густо усыпан костылями вида «промежуточная структура-указатель» как раз для развязки памяти значения и вспомогательных структур, переживающих объекты. По-хорошему это костыль и за такое нужно бить по рукам, потому что это мягко говоря не «zero overhead». Тебя не смущает, что пришлось делать столько приседаний, тебя не смущает, что тебе при разработке собственных аналогов придется делать столько же приседаний?

Я не устаю поражаться способностям крестовиков избирательно видеть проблемы. Посреди стола насрана огромная куча говна, но «мне не мешает, это не проблема». И ладно бы STL-подобный подход, который ты предлагаешь, решал бы проблему корректной работы с памятью, но он не решает, оставляя десятки способов прострелить себе ногу:
https://en.cppreference.com/w/cpp/container#Iterator_invalidation
И даже после того, как ты научился обходить минное поле, насоздавал промежуточных оберток и итераторов, то внезапно выясняется, что есть еще одна НЕПРОБЛЕМА — сообщения об ошибках решительно нечитаемы:

rtmap.cpp: In function `int main()':
rtmap.cpp:19: invalid conversion from `int' to `
   std::_Rb_tree_node<std::pair<const int, double> >*'
rtmap.cpp:19:   initializing argument 1 of `std::_Rb_tree_iterator<_Val, _Ref,
   _Ptr>::_Rb_tree_iterator(std::_Rb_tree_node<_Val>*) [with _Val =
   std::pair<const int, double>, _Ref = std::pair<const int, double>&, _Ptr =
   std::pair<const int, double>*]'
rtmap.cpp:20: invalid conversion from `int' to `
   std::_Rb_tree_node<std::pair<const int, double> >*'
rtmap.cpp:20:   initializing argument 1 of `std::_Rb_tree_iterator<_Val, _Ref,
   _Ptr>::_Rb_tree_iterator(std::_Rb_tree_node<_Val>*) [with _Val =
   std::pair<const int, double>, _Ref = std::pair<const int, double>&, _Ptr =
   std::pair<const int, double>*]'
E:/GCC3/include/c++/3.2/bits/stl_tree.h: In member function `void
   std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(_II,

   _II) [with _InputIterator = int, _Key = int, _Val = std::pair<const int,
   double>, _KeyOfValue = std::_Select1st<std::pair<const int, double> >,
   _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int,
   double> >]':
E:/GCC3/include/c++/3.2/bits/stl_map.h:272:   instantiated from `void std::map<_
Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _Input
Iterator = int, _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = st
d::allocator<std::pair<const int, double> >]'
rtmap.cpp:21:   instantiated from here
E:/GCC3/include/c++/3.2/bits/stl_tree.h:1161: invalid type argument of `unary *

Это обычное сообщение об ошибке STL. Это не проблема по-твоему, так и надо, так и задумывалось?

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

Я не знаю, на что ты отвечал, но я в своем цитируемом сообщении вижу явное сравнение с GC. Defer — это не вариант сборки мусора. Если говорить про языки без GC, то я прежде всего топил за явный возврат и обработку ошибки, а не про defer.

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

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

Надежности, стабильности, и так далее.

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

сообщения об ошибках решительно нечитаемы

они еще и не по-русски нечитаемы! решительно ничего не понятно. … впрочем, хорошо что не китайский.

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

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

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

Мертворожденная инициатива, поскольку в C++ абсолютно легальны небезопасные операции с указателями, который ты никакими способами не отследишь. И нет, declare_reachable не прокатывает, поскольку по сути выводит объект из-под механизма сборки мусора — а тогда зачем этот сборщик вообще нужен? Де-факто поддержки GC в C++ не существует — ее наконец формально убрали с концами из стандарта.

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

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

Как это «никого не волнует»? Меня волнует. Менее очевидный факт — крестовики «продают» именно это самое умение понимать смысл таких простыней. Как питонисты противятся любым улучшениям питона, поскольку они уже заучили наизусть все названия ad-hoc методов, предназначеных для обхода недостатков самого питона. Неочевидное следствие из обоих аргументов — крестовики и питонисты неохотно мигрируют на другие инструменты, поскольку это нивелируют ценность времени, потраченного на изучения путей обхода проблем. Некоторые прямо так себя и позиционируют «я мастерски умею обходить все проблемы C++, а больше я ничего не умею. Зачем мне ваш Go? Я свой выбор уже сделал».

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

Как это «никого не волнует»? Меня волнует.

а ты не волнуйся. это лишь эффект неожиданности.

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

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

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

предложи «неубогую» систему встроенных типов. ты вообще кто?

Посмотри на Rust хотя бы. При всем моем не уважении к оному. Эти типы данных совсем не новы, те же полноценные алгебраические типы были уже в Hope (1970), куцая форма оных попала в Си и Паскаль.

Массив можно было в язык добавить? Можно, почему-то в паскале они были, но в Си попало черт знает что, и это черт знает что в доработанной форме попало в кресты, став «черт знает что++».

Строки. СТРОКИ. Почему нельзя было сделать строки? Ладно, массивы, кастомный тип данных и всё такое. Только не надо мне рассказывать про юникод — в 80-е никакого юникода не было и большая часть IT индустрии считала, что в мире кроме латиницы больше алфавитов не существует. Причем, что характерно, Borland почти бесшовно перевел строки с однобайта на юникод (я лично занимался переводом многомиллионника), так что не надо мне рассказывать про ломающие изменения.

Эти структуры данных развивались в разных формах в 70-е, но в 80-е про них уже прекрасно знали, так что оправдания у Страуструпа нет, кроме «а я не знал» или «да мне пофик, лишь бы сдать руководству AT&T проект». Например, ты представляешь, насколько проще было бы работать с языком, если бы шаблоны позволяли передавать список типов-полей-функций и итерировать обычным кодом по этим спискам? А то и map-filter-reduce. Вместо вариадичных шаблонов с итерацией через рекурсию. И человеческая compile-time интроспекция типов вместо голых стен и SFINAE.

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

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

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

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

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

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

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

там сообщение о первичной ошибке жеж -

rtmap.cpp:19: invalid conversion from `int' to `
   std::_Rb_tree_node<std::pair<const int, double> >*'

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

к тому ж отцы плюсов ввели «концепты» чтоб такие вот ошибки ловить быстрее.

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

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

Ты знаешь, паскалевый кодер, который работал со мной и с которым вместе мы перешли на JS, тоже имел больше опыта по паскалю, чем я. Но в его случае было то, что в технологии нейросеток называется «переобучение», то есть, он забил большую часть своих мозгов какими-то узкоспециализированными штуками, которые, конечно, помогают в разработке здесь и сейчас, но становятся бесполезными при смене обстановки — даже при смене версии паскаля. Например, в паскале появились лямбды и STL-подобные контейнеры, но он до сих пор пишет на старом паскале, который он так тщательно изучил.

Продолжая аналогию, ты можешь понять, почему дефолтная опция компиляции сорцов ядра "-std=gnu89". и лишь совсем недавно Торвальдс надумал перейти на C11 — потому что все ключевые разработчики заучили до дыр фичи C89/C90, а также мастерски овладели работой с Vim, и потому не желают признавать, что разрешение мониторов за 30 лет намного выросло, помимо клавиатуры появились другие устройства ввода, и даже клавиатура изменилась со времен VT100, на ней есть есть намного больше кнопок, и эти кнопки даже можно нажимать одновременно — ОС способна передавать все подобные нажатия программе, а не только отдельные Ctrl+Key комбинации.

По этой причине не важно, сколько ты тренировался писать на C++03, если твой проект пишется на C++11, важно лишь твое актуальное умение писать на C++11 и общие навыки кодописания «на листке бумаги».

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

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

Так я ж не спорю. Но здесь ошибка элементарная. Помню, я недавно чуть с ума не сошел от ошибки, которая вообще не связана с STL: мне компилятор талдычил про какое-то «overloaded constructor resolution», выдавал список конструкторов, но ничего в ошибке не говорило о настоящей проблеме. А проблема была из-за того, что один шаблонный тип влиял на другой шаблонный тип, второй тип передавался в конструктор, а конструктор в C++ всегда перегружен — потому вместо того, чтобы фокусироваться на цепочке шаблонных типов, GCC прилип к перегруженным конструкторам.

К чему это я? Дополнительные движущиеся части в реализации — это всегда проблема, это не бесплатно, потому написать простой ясный ad-hoc алгоритм деструкции взаимно связанных объектов в одном месте получается дешевле, чем лепить типичный крестовый универсальный exception-safe механизм деструкции с нечитаемыми сорцами и сообщениями об ошибках, который потом все равно упадет с сегфолтом в рантайме, потому что ты ж читай комментарий к методу, который нельзя вызывать для таких-то итераторов при таких-то операциях.

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

STL густо усыпан костылями вида «промежуточная структура-указатель» как раз для развязки памяти значения и вспомогательных структур, переживающих объекты.

Примеры.

По-хорошему это костыль и за такое нужно бить по рукам, потому что это мягко говоря не «zero overhead»

Напомню, что zero overhead – это не «бесплатно», что бы ни имелось в виду в предыдущем предложении.

Это обычное сообщение об ошибке STL. Это не проблема по-твоему, так и надо, так и задумывалось?

Да. Не вижу проблем. Сообщение об ошибке содержит исчерпывающую информацию об этой ошибке. В MSVS есть «сокращенный» вывод ошибок с красивыми рюшечками, а есть полный в текстовом виде. Каким все пользуются? Правильно.

Defer — это не вариант сборки мусора.

В моем предложении действительно слились defer и финализаторы. Я рассматривал их по отдельности как возможные альтернативы основанному на ctor-dtor RAII. Впрочем, крестовое RAII позволяет без труда реализовать defer полностью стандартными средствами.

Надежности, стабильности, и так далее.

Все хорошее и ничего плохого. Конкретно какие проблемы не позволяют RAII дать какие гарантии безопасности чего?

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

Разумеется. Эта ссылка была приведена в качестве иллюстрации того, как С++ попытался косить под более высокоуровневые языки на заре своего становления.

Де-факто поддержки GC в C++ не существует

И никогда не существовало.

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

Во всех ли случаях, где оно применяется, необходимо применять именно его?

откуда же знать? это надо быть Селестой-7000.

главное, что инструмент ЕСТЬ и его применять, при необходимости, можно.

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