В смысле стандартов C и C++, кстати, указатель как раз объект — хранящаяся по какому-то адресу значение (адрес чего-то другого).
Если выражаться терминами стандарта C++… Но ведь это не верно по сути, поскольку указатель, как и многие другие типы в C++, обладает бо́льшим числом свойств, чем хранит фактически. Ну, например, настоящий тип, валидность объекта по адресу, факт владения, факт разделения владения, число указателей на объект и тп. Они являются свойствами указателя, свойствами адреса, но!.. Адрес — не объект, наоборот, у объекта есть свойство «адрес». А указателям нужно подключать std::shared_ptr\std::weak_ptr для того, чтобы эти свойства явно иметь. И даже так, многие проблемы остаются нерешёнными.
P.S. Можно ниже устроить срач на тему «Является ли валидность (и тп) объекта по адресу свойством указателя, свойством адреса или даже самого объекта?». Тема богатая для срачей, но абсолютно бессмысленная по сути, поскольку в самом языке указатель на любой адрес, отличный от nullptr, является валидным. То есть, с точки зрения языка не существует невалидных объектов. Просто некоторые из этих валидных объектов могут быть не очень съедобными для среды выполнения. По стандарту это так, а по сути — мы все знаем, как.
P.P.S. Да, я знаю, что валидность объектов по адресу гарантируется только при условии получения этого адреса от new или оператора &. Но вам ведь ясно написали «гарантируется». Это не значит, что нельзя его получать из malloc или 100500[myArray]. Или вообще наплевать на это дело и использовать численные значения, сидя в микроконтроллере.
Думаю, это о том, что генерация SQL-запросов занимает время, преобразование данных, если производится, занимает время, сами запросы не оптимальны, так что их выполнение занимает дополнительное время. И не всегда можно предсказать, насколько всё будет плохо.
Что касается химер, чисто ИМХО, они появляются в тот момент, когда некие сущности из-за особенности языка опускаются из описания. Например, тот же указатель в C++ — это «связь 1-1_либо_много», точный тип которой нельзя получить из контекста, а сам указатель не имеет собственного объекта и\или состояния. Поэтому реализовать в C++ ORM средствами лишь самого языка нельзя, а любые попытки впихнуть компромиссный вариант натыкаются на боль и унижение (на выбор, тонны макросов или работа только с небольшим подмножеством языка). Единственное решение — избавиться от сырых указателей и явно прописывать этот самый объект. А оно не самое тривиальное.
Ну тут, как бы, непонятно за что биться. Я сам, разумеется, был бы счастлив жить в мире, где прослушки всего на свете нету. И где нормальные законопослушные граждане не обязаны предъявлять товарищмайору все свои разговоры с женой.
И жили бы, будь все граждане нормальные и законопослушные. Но имеем мы то, что имеем.
Не то, чтобы я защищаю автора, — он сам за себя ответит, но статья как чисто прикладная задача очень интересна. Если нужно создавать объекты — их нужно создавать (привет, К.О.), а разные сценарии работы требуют разные способы инициализации данных. К примеру, правильное использование Cython требует наличие головы и рук, которые должны расти хотя бы из жопы, а не в неё. То же с тестами.
Так что с некоторыми аргументами автора я полностью согласен: если на питоне он может это написать относительно качественно и быстро — не надо давать ему гранату, пусть и дальше пишет на питоне.
Были проблемы при установке на машинах со слегка отличной архитектурой
Если вы не планируете разворачиваться на Pentium 2, проблем быть не должно. По крайней мере, на актуальных архитектурах, включая атомы.
не думаю, что профит был бы намного больше
Зависит от квалификации программиста и сценариев использования. Тут у недавнего поста уравнение Френеля для миллиона нормалей считается 3-5 секунд. habr.com/company/otus/blog/433588
Ну, вот, смотрите, берём самый тупой пример, переписанный с вашего. Я использую старые версии компилятора, в которых нет any, поэтому данные будут храниться либо в map<string,string>, либо в структуре.
Исходники
struct Dict
{
std::string name;
int test_data;
std::string test_data2;
std::vector<int> test_data3;
std::map<std::string,std::string> properties;
};
typedef std::vector<std::map<std::string,std::string>> dictionary;
typedef std::vector<Dict> dictionary2;
int range_attempts = 1000000;
std::vector<int> range(int N) {
std::vector<int> v (N, 0);
for (int i = 1; i < N; ++i) {
v[i] = i;
}
return v;
}
void runtest(dictionary & dict)
{
long long a, b;
QElapsedTimer timer;
dict.clear();
timer.start();
dict.assign(range_attempts, std::map<std::string,std::string>());
for (int i = 0; i < range_attempts; ++i) {
dict[i]["name" ] = "test_" + std::to_string(i);
dict[i]["test_data" ] = std::to_string(i);
dict[i]["test_data2"] = std::to_string(i);
dict[i]["test_data3"] = std::to_string(i);
}
a = timer.elapsed();
dict.clear();
b = timer.elapsed();
qDebug() << a * 0.001 << b * 0.001;
}
void runtest2(dictionary2 & dict)
{
long long a, b;
QElapsedTimer timer;
dict.clear();
timer.start();
dict.assign(range_attempts, Dict());
for (int i = 0; i < range_attempts; ++i) {
dict[i].name = "test_" + std::to_string(i);
dict[i].test_data = i;
dict[i].test_data2 = std::to_string(i);
dict[i].test_data3 = range(10);
}
a = timer.elapsed();
dict.clear();
b = timer.elapsed();
qDebug() << a * 0.001 << b * 0.001;
}
void test(QWidget *parent)
{
dictionary dict;
for (int i = 0; i < 10; ++i) {
runtest(dict);
}
dictionary2 dict2;
for (int i = 0; i < 10; ++i) {
runtest2(dict2);
}
}
Собираем в gcc 4.8.*, запускаем, получаем в среднем 24.203 и 10.115 секунд для чисто строкового контейнера и структуры, соответственно. ОГО! У вас куда быстрее, чем у меня, есть чему порадоваться! Не спешите. Берём MSVC 2014 — и получаем 2.4 и 0.86 секунд. Да, компилятор решает. Получается, у вас быстрее? Есть одно «НО». Intel Core2 CPU 6420 @ 2.13 GHz
Запускаем на Ryzen 3 2200G и видим уже 1.3 и 0.5 секунд для gcc и 1.05 и 0.39 секунд для MSVC. И потребление памяти на уровне 220 Мб и 180 Мб, соответственно. Опция компиляции -O2 без агрессивных ключей. Без оптимизации под задачи, без каких-либо ухищрений. Без многопотока.
А я повторю вопрос: причём тут C++? Зачем использовать Cython без его использования? Вопрос это не такой простой и глупый, как кажется. Что было бы, если бы вы не контейнер втянули, а сам словарь написали на С++, а в питон пробросили методы?
Я описал почему мы используем так.
Нет, не описал. «Мы используем -O1» — это не аргумент.
Почему всего лишь -O1? Хотя бы уж -Ofast -ftree-vectorize -msse2 Код для вектора тоже было бы вежливо предоставить. А так мы сравниваем бульдога с носорогом. Погодите-ка… Это сравнение питоновых list и vector? А причём тогда
проверить теорию одного коллеги, что C++ vector мог бы быстрее справиться с задачей, чем CPython list.
Или посыл статьи в том, что использовать нативные контейнеры обычно более лучшая идея, чем, не разобравшись, пихать что-то? С этим не поспоришь.
Во-первых, мы с вами друг другу не противоречим.
Во-вторых, патентуется именно алгоритм программы, а не исходник. Блок-схема.
В третьих, зависит от задач форматов. Создать что-то типа SWIFT стоит очень дорого только из-за процедуры согласования со всеми заинтересованными сторонами. Ясен пень, такую систему обложат всеми видами юридических защит. У нас же разработок такого уровня и степени согласований не так уж много, из чего следует посыл статьи.
Моё ИМХО, ТС напоролся на голые цифры и запаниковал, не рассмотрев сути за ними. А суть в том, что мы сами не знаем своих успехов, которых более чем достаточно. А то, что знаем, необоснованно принижаем по непонятным причинам.
В ИТ есть одна очень неприятная проблема. Для того, чтобы потроллить патентом, нужно доказать, что алгоритм из патента использовался. Учитывая, что компиляция и\или обфускация значительно преображают исходники, сделать это бывает весьма и весьма непросто. Особенно, если это не формат хранения данных и не набор пиктограмм.
Поэтому у нас многие и не озадачиваются патентами. Да и не только у нас, посмотрите на мировое ИТ: сейчас все от патентования перебираются в OpenSource. Конкуренция высокая — куда проще кормиться с донатов, поддержки и лицензий на продажу побочных продуктов, чем пытаться продавать свой закрытый продукт до получения первых положительных результатов пользователями. Исключение — совсем крупные продукты с долгой историей.
Тут же очень много всего можно вспомнить, что C++ кладёт на разработчиков. Та же валидность указателей. Вот, например, что будет, если кастануть char* в T*? Ладно, вопрос попроще, что будет, если кастануть &(char[0]) в char*? О, это же UB!!! Как так? Нельзя! Нужно запретить! Бросать исключения! Мы же можем залезть в левую память!
Звучит один-в-один как у вас. У нас же не определено, что будет, если указатель наложился на область памяти, которая не совсем класс. Которая меньше, чем класс, иначе устроена, чем класс и тд и тп. И у нас нет гарантий, что на всех платформах адреса массива и его первого элемента совпадают. И?
Если каждое UB завесить такими шорами, ничего хорошего мы не получим. Мне не нужно проверять каждый указатель на валидность каста. Мне не нужно проверять каждое сложение на переполнение. Если вам нужно, вы либо неправильно написали программу, либо неправильно выбрали инструментарий. И тут имеется в виду не язык.
1) Так-то есть T foo() throw(Types,...);, которой никто не пользуется и которая уже обозначена устаревшей.
2) Зависит от реализации компилятора. Некоторые просто делают условный переход, особенно, на микроконтроллерах. Там, где механизм исключений введён, работает и не транслируется в /dev/null.
5) Вероятно, имелось в виду, что если исключение, которое брошено тебе, пролезает через некоторую функцию, нет гарантии, что оно до тебя дойдёт, спасибо catch(...)
11*) Исключения не могут выполнять ту же функцию, которую на них накладывают в других языках из-за оптимизирующего компилятора. В частности, стек результирующего кода чаще всего не эквивалентен вашим исходникам, да и порядок операций не обязан совпадать. Учитывая, что оптимизирующий компилятор является чуть ли не фишкой языка (не является, но что такое плюсы без -O3?), этот пункт не стоит списывать в «реализацию» или «придирки». Хотя да, локализация ошибки — это не основное назначение исключений, так что пункт под звёздочкой.
12) Расширение списка стандартных исключений серьёзно ломает обратную совместимость языка и увеличивает накладные расходы. Например, исключение по целочисленному переполнению добавляет по одному условному переходу к каждой операции +,-,*. Код для них должен увеличиться на порядок, с одной-двух операций до пяти-дюжины на разных системах. Эта та цена, которую вы требуете, но которую я не желаю платить, потому что я сам способен проверить их на входе.
Собственно, из пункта 12 (и 2) и исходит неоднократно предложенное вам решение использовать уже написанные и доступные из буста тип safe или библиотеку математических исключений.
Как только люди, выделяющие деньги, начнут ТРЕБОВАТЬ от IT ответственности, так эта ответственность и появится.
Да, да, конечно, не мы такие, жизнь такая. Вот когда она нас заставит, ох, как мы раскорячимся! Только напомните, как много сайтов до сих пор работают с heartbleed? М?
Собственно, там где требуют, она и так есть.
Казалось бы, причём тут VPN, RuTracker, Telegram и Tor?
Заметьте, как сейчас любое их упоминание в негативном ключе вызовет бурную отрицательную реакцию сообщества.
Эх, а ведь корень зла в том, что IT — ужасно безответственная сфера. Люди здесь инфантильны и подвержены сиюминутным влияниям, имеющим долгосрочные негативные последствия.
Например, какова цена ошибки для конкретного программиста? Ну, вот, «Протон» упал из-за неправильной прошивки, и? А обновление Windows свежее, которое тёрло пользовательские данные, что было МелкоМягким программистам? В худшем случае виновников уволили, а, в основном, ничего им не бывает, пожурят отдел и всё. То же с маркетологами, HR и прочими бухгалтерами. Сравните это с водителями, пилотами или моряками, чьи ошибки стоят им жизни. С врачами, которые все на пороге тюрьмы, собственно, сидят.
Поэтому у нас такое легкомысленное отношение как к другим, так и к себе. «Скопировать резюме и разослать», «Скопировать тестовое задание и разослать», «Скопировать решение тестового задания и разослать», «Собрать решения тестовых заданий и rand()%N», «Собрать положительные ответы и sort(зарплата)». 50 законов по пути нарушили? «Этого не было, если оно не попало в вебархив.» И это мы себя так с лучшей стороны проявляем.
Кто кроме разработчика приложения, может решать вообще хоть что-то в его приложении?
А что разработчик вообще может решать в своём приложении? Вы, такие умные, на JS можете сказать хромиуму уйти на йух со своими манифестами и разрешениями? Или без разрешения этой среды-библиотеки вы даже пукнуть не смеете? Можете не отвечать, это риторический вопрос.
А вы бы предпочли, чтобы эти приложения вообще никогда не работали? Эти недокументированные апи использовались не от хорошей жизни, а потому что без них было не обойтись на тот момент.
Или можно было, пожертвовав частью функционала или толикой производительности. Собственно, так и пишут те же сайты для IE.
Но есть у нас, например, особенные сайты, которые используют дырки движка IE, ActiveX и плагины для обеспечения защищённого соединения с тем же банком. Ну же, скажите, «у них не было выбора», «либо так, либо никак», «не всем можно мазилу» и «а вы бы предпочли, чтобы у них вообще не было вебморды». Да, я бы предпочёл без вебморды, чем ту, которая не работает.
А чья же? Кто, кроме разработчика библиотеки, может решать, где чья зона ответственности в его библиотеке?
Если дать пользователю свободу, будет та же фигня, что с WinAPI. С тем самым, который в Win10 и Wine эмулируют баг-в-баг, потому что иначе половина софта не работает. Потому что пользователи привязались к незадокументированным функциям или ошибочному поведению вместо того, чтобы чётко следовать оговоренному в документации контракту. (Хотя, согласен, документация там тоже не самая удачная.)
Да, другое… Старый добрый ной прикладного программиста про фишки языка общего назначения с дырками под системные нужды.
Вы на секунду притормозите и задумчиво ответьте на 3 вопроса:
На всех ли платформах, в которые может C++, можно реализовать исключения, и разумно ли это?
На всех ли платформах, в которые может C++, возможно динамическое выделение памяти и существуют new, delete и nullptr?
На всех ли платформах, в которые может C++, существует операция деления?
Ответы на эти 3 вопроса очень сильно помогут вам понять, почему вы и qw1 уводите обсуждение не в ту сторону, из которой исходит проблема. Давайте лучше пообсуждаем, довольны ли мы тем, что C++ до сих пор сражается за свою универсальность.
UPD1: Алсо, я понимаю, чем тот же злосчастный nullptr_t отличается от T* на этапе компиляции. А в рантайме? Как это всё должно выглядеть в рантайме? Как в java: указатель и (утрирую) килобайт метаданных сверху?
P.S. vintage, я говорил о математике как библиотеке языка программирования, а не о талмудах, которыми пятиклассники друг друга избивают. Извините, если ранил ваши религиозные чувства.
Может, вы слишком сильно зациклились на своей архитектуре? Напомню, C++ не только на AMD64 существует.
Реальная проблема в том, что это не должно быть UB.
Хм?
На AVR я могу разыменовать 0x0000, ибо это валидный адрес для ROM'а. На нём же я могу делить на ноль без падений хотя бы потому, что AVR не может упасть. Это микроконтроллер, а не кирпич. Если у вас есть более ёмкий термин для такого поведения, чем UB, — пожалуйста, предложите его. Ну и так, до кучи, результат деления целого на ноль — целочисленный NaN. Валидное значение для математики. Но, так как его реализации нет на большинстве архитектур, он не описан в стандарте, просто упоминается вскользь. А поведение разнится от пропуска операции до системного прерывания.
А что касается остального, да, всё верно. Только всё ваше нытьё в комментариях блокируется простым
Уважайте своего пользователя, не будьте мудаками! Пишите понятные интерфейсы с ожидаемым поведением Проверяйте все входные параметры на валидность при входе в функцию и правильно описывайте ошибки, чтобы ему не нужно было читать комментарии и материться.
ИМХО, должно было получиться обидно. Ну а как иначе? Вы сами написали в статье, что корректность состояния должна задаваться программистом, а не языком. У вас явная гарантия отсутствия однообразного поведения в разных условиях, описанная в стандарте. Ещё раз. Вам явно пишут, что результат операции неизвестен, так как зависит от программистов архитектуры+компилятора. Но нет, вы не довольны. И где ваша свобода выбора?
P.S. Можно ниже устроить срач на тему «Является ли валидность (и тп) объекта по адресу свойством указателя, свойством адреса или даже самого объекта?». Тема богатая для срачей, но абсолютно бессмысленная по сути, поскольку в самом языке указатель на любой адрес, отличный от nullptr, является валидным. То есть, с точки зрения языка не существует невалидных объектов. Просто некоторые из этих валидных объектов могут быть не очень съедобными для среды выполнения. По стандарту это так, а по сути — мы все знаем, как.
P.P.S. Да, я знаю, что валидность объектов по адресу гарантируется только при условии получения этого адреса от new или оператора &. Но вам ведь ясно написали «гарантируется». Это не значит, что нельзя его получать из malloc или 100500[myArray]. Или вообще наплевать на это дело и использовать численные значения, сидя в микроконтроллере.
Что касается химер, чисто ИМХО, они появляются в тот момент, когда некие сущности из-за особенности языка опускаются из описания. Например, тот же указатель в C++ — это «связь 1-1_либо_много», точный тип которой нельзя получить из контекста, а сам указатель не имеет собственного объекта и\или состояния. Поэтому реализовать в C++ ORM средствами лишь самого языка нельзя, а любые попытки впихнуть компромиссный вариант натыкаются на боль и унижение (на выбор, тонны макросов или работа только с небольшим подмножеством языка). Единственное решение — избавиться от сырых указателей и явно прописывать этот самый объект. А оно не самое тривиальное.
Так что с некоторыми аргументами автора я полностью согласен: если на питоне он может это написать относительно качественно и быстро — не надо давать ему гранату, пусть и дальше пишет на питоне.
Зависит от квалификации программиста и сценариев использования. Тут у недавнего поста уравнение Френеля для миллиона нормалей считается 3-5 секунд. habr.com/company/otus/blog/433588
Ну, вот, смотрите, берём самый тупой пример, переписанный с вашего. Я использую старые версии компилятора, в которых нет any, поэтому данные будут храниться либо в map<string,string>, либо в структуре.
Собираем в gcc 4.8.*, запускаем, получаем в среднем 24.203 и 10.115 секунд для чисто строкового контейнера и структуры, соответственно. ОГО! У вас куда быстрее, чем у меня, есть чему порадоваться! Не спешите. Берём MSVC 2014 — и получаем 2.4 и 0.86 секунд. Да, компилятор решает. Получается, у вас быстрее? Есть одно «НО». Intel Core2 CPU 6420 @ 2.13 GHz
Запускаем на Ryzen 3 2200G и видим уже 1.3 и 0.5 секунд для gcc и 1.05 и 0.39 секунд для MSVC. И потребление памяти на уровне 220 Мб и 180 Мб, соответственно. Опция компиляции -O2 без агрессивных ключей. Без оптимизации под задачи, без каких-либо ухищрений. Без многопотока.
Делайте выводы сами.
Нет, не описал. «Мы используем -O1» — это не аргумент.
Код для вектора тоже было бы вежливо предоставить. А так мы сравниваем бульдога с носорогом.Погодите-ка… Это сравнение питоновых list и vector? А причём тогдаИли посыл статьи в том, что использовать нативные контейнеры обычно более лучшая идея, чем, не разобравшись, пихать что-то? С этим не поспоришь.
Во-вторых, патентуется именно алгоритм программы, а не исходник. Блок-схема.
В третьих, зависит от задач форматов. Создать что-то типа SWIFT стоит очень дорого только из-за процедуры согласования со всеми заинтересованными сторонами. Ясен пень, такую систему обложат всеми видами юридических защит. У нас же разработок такого уровня и степени согласований не так уж много, из чего следует посыл статьи.
Моё ИМХО, ТС напоролся на голые цифры и запаниковал, не рассмотрев сути за ними. А суть в том, что мы сами не знаем своих успехов, которых более чем достаточно. А то, что знаем, необоснованно принижаем по непонятным причинам.
Поэтому у нас многие и не озадачиваются патентами. Да и не только у нас, посмотрите на мировое ИТ: сейчас все от патентования перебираются в OpenSource. Конкуренция высокая — куда проще кормиться с донатов, поддержки и лицензий на продажу побочных продуктов, чем пытаться продавать свой закрытый продукт до получения первых положительных результатов пользователями. Исключение — совсем крупные продукты с долгой историей.
Звучит один-в-один как у вас. У нас же не определено, что будет, если указатель наложился на область памяти, которая не совсем класс. Которая меньше, чем класс, иначе устроена, чем класс и тд и тп. И у нас нет гарантий, что на всех платформах адреса массива и его первого элемента совпадают. И?
Если каждое UB завесить такими шорами, ничего хорошего мы не получим. Мне не нужно проверять каждый указатель на валидность каста. Мне не нужно проверять каждое сложение на переполнение. Если вам нужно, вы либо неправильно написали программу, либо неправильно выбрали инструментарий. И тут имеется в виду не язык.
2) Зависит от реализации компилятора. Некоторые просто делают условный переход, особенно, на микроконтроллерах. Там, где механизм исключений введён, работает и не транслируется в /dev/null.
5) Вероятно, имелось в виду, что если исключение, которое брошено тебе, пролезает через некоторую функцию, нет гарантии, что оно до тебя дойдёт, спасибо catch(...)
11*) Исключения не могут выполнять ту же функцию, которую на них накладывают в других языках из-за оптимизирующего компилятора. В частности, стек результирующего кода чаще всего не эквивалентен вашим исходникам, да и порядок операций не обязан совпадать. Учитывая, что оптимизирующий компилятор является чуть ли не фишкой языка (не является, но что такое плюсы без -O3?), этот пункт не стоит списывать в «реализацию» или «придирки». Хотя да, локализация ошибки — это не основное назначение исключений, так что пункт под звёздочкой.
12) Расширение списка стандартных исключений серьёзно ломает обратную совместимость языка и увеличивает накладные расходы. Например, исключение по целочисленному переполнению добавляет по одному условному переходу к каждой операции +,-,*. Код для них должен увеличиться на порядок, с одной-двух операций до пяти-дюжины на разных системах. Эта та цена, которую вы требуете, но которую я не желаю платить, потому что я сам способен проверить их на входе.
Собственно, из пункта 12 (и 2) и исходит неоднократно предложенное вам решение использовать уже написанные и доступные из буста тип safe или библиотеку математических исключений.
Казалось бы, причём тут VPN, RuTracker, Telegram и Tor?
Заметьте, как сейчас любое их упоминание в негативном ключе вызовет бурную отрицательную реакцию сообщества.
Например, какова цена ошибки для конкретного программиста? Ну, вот, «Протон» упал из-за неправильной прошивки, и? А обновление Windows свежее, которое тёрло пользовательские данные, что было МелкоМягким программистам? В худшем случае виновников уволили, а, в основном, ничего им не бывает, пожурят отдел и всё. То же с маркетологами, HR и прочими бухгалтерами. Сравните это с водителями, пилотами или моряками, чьи ошибки стоят им жизни. С врачами, которые все на пороге тюрьмы, собственно, сидят.
Поэтому у нас такое легкомысленное отношение как к другим, так и к себе. «Скопировать резюме и разослать», «Скопировать тестовое задание и разослать», «Скопировать решение тестового задания и разослать», «Собрать решения тестовых заданий и rand()%N», «Собрать положительные ответы и sort(зарплата)». 50 законов по пути нарушили? «Этого не было, если оно не попало в вебархив.» И это мы себя так с лучшей стороны проявляем.
Или можно было, пожертвовав частью функционала или толикой производительности. Собственно, так и пишут те же сайты для IE.
Но есть у нас, например, особенные сайты, которые используют дырки движка IE, ActiveX и плагины для обеспечения защищённого соединения с тем же банком. Ну же, скажите, «у них не было выбора», «либо так, либо никак», «не всем можно мазилу» и «а вы бы предпочли, чтобы у них вообще не было вебморды». Да, я бы предпочёл без вебморды, чем ту, которая не работает.
Если дать пользователю свободу, будет та же фигня, что с WinAPI. С тем самым, который в Win10 и Wine эмулируют баг-в-баг, потому что иначе половина софта не работает. Потому что пользователи привязались к незадокументированным функциям или ошибочному поведению вместо того, чтобы чётко следовать оговоренному в документации контракту. (Хотя, согласен, документация там тоже не самая удачная.)
Вы на секунду притормозите и задумчиво ответьте на 3 вопроса:
На всех ли платформах, в которые может C++, можно реализовать исключения, и разумно ли это?
На всех ли платформах, в которые может C++, возможно динамическое выделение памяти и существуют new, delete и nullptr?
На всех ли платформах, в которые может C++, существует операция деления?
Ответы на эти 3 вопроса очень сильно помогут вам понять, почему вы и qw1 уводите обсуждение не в ту сторону, из которой исходит проблема. Давайте лучше пообсуждаем, довольны ли мы тем, что C++ до сих пор сражается за свою универсальность.
UPD1: Алсо, я понимаю, чем тот же злосчастный nullptr_t отличается от T* на этапе компиляции. А в рантайме? Как это всё должно выглядеть в рантайме? Как в java: указатель и (утрирую) килобайт метаданных сверху?
P.S. vintage, я говорил о математике как библиотеке языка программирования, а не о талмудах, которыми пятиклассники друг друга избивают. Извините, если ранил ваши религиозные чувства.
Хм?
На AVR я могу разыменовать 0x0000, ибо это валидный адрес для ROM'а. На нём же я могу делить на ноль без падений хотя бы потому, что AVR не может упасть. Это микроконтроллер, а не кирпич. Если у вас есть более ёмкий термин для такого поведения, чем UB, — пожалуйста, предложите его. Ну и так, до кучи, результат деления целого на ноль — целочисленный NaN. Валидное значение для математики. Но, так как его реализации нет на большинстве архитектур, он не описан в стандарте, просто упоминается вскользь. А поведение разнится от пропуска операции до системного прерывания.
А что касается остального, да, всё верно. Только всё ваше нытьё в комментариях блокируется простым ИМХО, должно было получиться обидно. Ну а как иначе? Вы сами написали в статье, что корректность состояния должна задаваться программистом, а не языком. У вас явная гарантия отсутствия однообразного поведения в разных условиях, описанная в стандарте. Ещё раз. Вам явно пишут, что результат операции неизвестен, так как зависит от программистов архитектуры+компилятора. Но нет, вы не довольны. И где ваша свобода выбора?