Комментарии 150
Несомненно, это будет удачным стечением обстоятельств, если комитету за 25 лет удастся проделать такую "титаническую" работу.
Я не понимаю, почему комитет не задеприкейтит создание новых проектов на этом языке в пользу Раста, у которого эти проблемы были решены 5 лет назад. Наконец-то подход комитета С++ потихоньку начинает понимать проблематику и то, как это стоило бы решать в нормальных условиях. Но он решает проблему дат и файловой системы.
А кроме огромной кодовой базы (читай легаси кода), есть хоть какой-то смысл использовать C++ вместо Rust?
Как в конце 80х все массово перешли с Паскаля на C (вы в курсе, что изначально и MacOS и Windows на Pascal были написаны?), так и тут может произойти через 30 лет…
MacOS и Windows на Pascal были написаны?
Windows не была. И даже DOS не был. До версии 3.0 он был полностью написан на ассемблере. В 3.0 attrib.exe стал первой утилитой на C. Постепенно весь DOS был переписан на C. WinAPI 16 использовал соглашение вызовов __pascal ради экономии двух байт на стеке и того, что такой вызов был чуть быстрее. Что было важно для машин с десятками килобайт памяти и единицами мегагерц скорости.
Но свои версии компиляторов Pascal Microsoft делал до конца 80-х.
1. Компилятор Microsoft Pascal 1.10 — это 1981й год.
2. Первый компилятор C для IBM PC, Lattice C — это 1982й год.
3. Microsoft C 2.0 — это всё тот же самый Lattice C под другим брендом, только вышел он в 1984м.
Так на каком языке была написана Windows, если работа над ней началась в 1981м, а в 1983м безумный Стив Баллмер (которому пообещали, что «усё будет готово к 1983му и „наивный чукотский вьюноша“ поверил) устроил в Лас-Вегасе охренительную рекламу Windows (продукта, который не выйдет на рынок ещё два года)?
Другое дело, что до релиза эта версия (в отличие от MacOS) не добралась… это да — но изначально она писалась на смеси Assembler'а (без этого ни одна OS не обходится, вопрос лишь в пропорциях) и Pascal'я…
Другое дело, что до релиза эта версия (в отличие от MacOS) не добралась… это да — но изначально она писалась на смеси Assembler'а (без этого ни одна OS не обходится, вопрос лишь в пропорциях) и Pascal'я…
Так первая Windows по вашему мнению была написана, или же был написан некий не увидевший свет концепт?
- Мощная система типов унаследованная от Haskell вместо ООП + аффинные типы и следующие из них статические гарантии(memory safety, fearless concurency, итп итд)
- Модули
- Стандартный пакетный менеджер вместо зоопарка несовместимых друг с другом решений
- Стратегия развития языка(эпохи, RFC, вот это вот всё)
- Синтаксис и стандартная библиотека без груза многолетней поддержки обратной совместимости
- Синтаксическое разделение языка на safe и unsafe подмножества, которое позволяет легко определить где в коде используется чорная магия и прочее колдунство)
И это только то, что сразу на ум пришло.
А что касается легаси, то он никуда не денется. И принятие нового стандарта не превратит автоматически «8.5 миллионов строк C++ кода» хромиума в C++ код стандарта C++23.
Указатели мощная концепция, которая почти всегда не нужна, ибо ссылки практически все сценарии поддерживают лучше. Для оставшихся редких задач да, можно использовать указатели, и пометить соответствующие блоки типа «beware, here be dragons».
До тех пор, пока в Rust присутствует unsafe
блок, комментарий про некомпетентных программистов является справедливым.
Я не согласен только с вашим определением «плохого языка», оно слишком категорично. Я не люблю называть языки, которые могут как-то приносить пользу, плохими. Возможно, я через чур оптимистичен.
Возможно, вы не правильно поняли меня про некомпетентность, я имел в виду не вас, а то, что всегда будут некомпетентные люди для любого языка, где есть такая возможность.
средний программист не вчера универ закончил, а полгода работы уже более чем достаточно научиться работать с памятью в современных плюсах.
конечно научился, а то бы у него программы падали постоянно.
но есть такой фактор как невнимательность.
невозможно 100% времени быть 100% сконцентрированным.
и главное — зачем?
если можно это перепоручить компилятору.
А кроме огромной кодовой базы (читай легаси кода)
А этого мало?
Была куча программистов на С++, которые тянули старый код годами.
Наняли новых (часть, конечно, переучили) и сделали глобальный рефакторинг.
И совсем не факт, что если бы наняли хороших архитекторов и потратили то-же время на рефакторинг получилось бы хуже.
Хром то, на C++ и не тормозит.
void copy(int* src, int* dest, int size) {
for(int i=0;i<size;++i) {
array[i] = dest[i];
}
}
Из-за стандарта плюсы обязаны производить лишние операции в цикле, чтобы соблюсти правила алиасинга. Хотя передавать одну и ту же ссылку (или даже пересекающиеся) в src и dst это явно автор не предполагал. Но если поставить __restrict__, то основной кейз становится таким же быстрым, но теперь в случае нарушение гарантий (кто-то случайно не то передал) последствия могут быть намного хуже.
Собственно, тезис простой и думаю вы с ним согласны: чем сильнее система типов, тем больше простор действий для оптимизатора. Тут вот небольшая заметка в качестве примера, как это происходит по шагам. Можете описать, согласны ли вы с выводами?
А зачем вам быстрый некорректный код, когда существующая система типов в Раст позволяет вам написать такой же быстрый код, но при этом корректный? Что мешает лично вам?
Ошибки совершают все, даже люди с 20-летним стажем. В любом языке. Но, может, лучше возложить часть нагрузки на язык, а не сваливать всю вину на программиста?
Всегда на такие "фразочки" отвечают: а покажите свой гитхаб. Более чем уверен, что если вы написали пару тысяч строк кода на С++, я найду в них багу. Ну-ка, товарищ, вперед!
Есть программа SphericalCowCAD. В этой программе есть функции Foo(x) и Bar(y). Функция Foo вызывается в M*N раз чаще (M>>0, N>>0) функции Bar. Оптимизатор многозадачной ОС исключает (в соответствии с парадигмой дефицита быстрой памяти) загрузку функции Bar из медленной долговременной памяти в быструю память. Вопрос: на каком языке программирования написана программа SphericalCowCAD?
1. Зачем вы передаёте указатель src, если потом не используете его?
2. Откуда взялся array? Это глобальная переменная?
3. Почему читаются значения из dest, когда по смыслу это место куда надо копировать, а не откуда?
Отсутствие проверки src и dest на null, и на равенство друг другу можно списать на то что это просто пример. Но в целом по коду вообще не понятно что он должен делать, и что вы хотите показать. Это выглядит как бессмыслица. Могу лишь предположить, что вы случайно запостили результат нескольких несогласованных между собой правок кода.
Да, в плюсах 1000 и 1 способ выстрелить себе в ногу, но в умелых руках и при должной осторожности можно делать действительно классные и быстрые вещи, например полноценный паттерн «состояние» на стеке
Насчет классных вещей — совсем не спорю. Есть языки, которые безопасны и там нельзя этого сделать — управляемые джавы и шарпы из таких. Есть плюсы где это можно сделать, но с безопасностью есть определенные проблемы. Раст на моей памяти первая удачная с моей точки зрения попытка усидеть на двух стульях. Более строгий анализатор с возможностью отключения проверок в некоторых местах (с явной аннотацией «я думаю тут все в порядке, но кто знает») мне кажется более продуктивен для разработчика, чем менее строгий. В конце концов всякие статические анализаторы для плюсов для того и придумали. Просто оказывается, что если запретить некоторые корректные, но сложноанализируемые вещи то анализатор становится намного полезнее. И пусть эти корректные вещи приходится либо переписывать так, чтобы уговорить компилятор пропустить их, либо воспользоваться unsafe. Но ведь во всем остальном проекте он будет помогать, а не мешать.
Я буквально на днях писал пример для интервью в одну компанию на расте. Писал часов 10, исправляя ошибки, в конце концов оно скомпилировалось. И это было бесподобно, потому что на моих ежедневных шарпах такого бы точно не произошло — NullRef где-нибудь или выход за границы массива — гарантированно. До этого у меня такое было всего один раз, когда я изучал хаскель. Там тоже происходит долгий диалог с анализатором, в конце которого получается рабочий продукт. Как по мне, это намного приятнее, чем сидеть с дебаггером.
Выход за границы на шарпе? Интересный вы код пишете, если не ходите по массиву, а вычисляется значения индексов на лету.
Ну и не помню когда вообще последний раз ловил npe.
А что это за тестовое, которое надо фигачить 10 часов? Можете в двух словах рассказать?
Что касается NRE — просто с трудом могу поверить, что есть человек, который с ними редко сталкивается. Наряду с KeyNotFoundException это самые противные исключения, контекст которых абсолютно непонятен, и которые просто являются бичом.
Что касается тестового: там просто поиск на графе, просто исполнение осложнялось несколькими условиями. Во-первых я писал на языке, который начал изучать в конце прошлого года серьезно, когда IDE наконец начали нормально работать. Во-вторых я плохо знаком с алгоритмами на графах, и например я долго думал об алгоритме упаковки матрицы в вектор так, чтобы при ресайзе не нужно было ничего копировать поэлементно (вот мой вариант, с которым мне кстати еще и помогли, если есть идеи, как улучшить — welcome). Ну и в-третьих в задании просили писать production-ready код, поэтому сюда добавляется время на тесты, XML-доки и вот это все.
А Stylo на Rust сделался с первого раза.
Вы так легко пишете «с первого раза»… а ведь целый Rust был создан.
предпринимались неоднократно
Попытки уровня «Взять и переписать с нуля»?
Вы так легко пишете «с первого раза»… а ведь целый Rust был создан.
Да, был. Именно потому что на нем эта задача оказалась проще.
Про fearless concurrency не слышали? Без Rust
такой подход невозможен.
Да, сейчас уже больше компонент из Servo втащили, что неплохо, но собственно многопоточность rust'а не требовала.
P.S. И ещё раз, я не против rust'а. Интересный эксперимент. Я против утверждений «без rust'а вы не сможете сделать XXX». Сможете. Вопрос в цене.
Вы невнимательно прочли. Комитет должен рекомендовать начинать писать новые проекты на Раст, а не на С++. Тогда всем будет счастье.
Ну что вы. Легаси — важное наследие, которое необходимо поддерживать.
Выше высказали дельную мысль: новые фичи языка не превратят легаси в безопасный код, все равно останутся сырые указатели, утечки, UB и прочие вещи.
Поэтому одним из возможных важных этапов С++ было бы… делегирование своего продолжения в Rust, где уже все это пофикшено. Надеюсь, вы поняли мою мысль)
Я не понимаю, почему комитет не задеприкейтит создание новых проектов на этом языке в пользу Раста
Может быть потому, что ребята, которые пилят раст, сами решают, что станет стандартом в их языке, и делегировать это право комитету в их планы не входит?
Или вы предлагаете тупо списать? :)
Можно форкнуть язык комитетом, который будет сам решать, какие фичи будут переползать в Раст-форк. А что, хороший план)
string_view
и span
не являются безопасными. Объект, на который они ссылаются, может быть удалён или перемещён, а вы и не заметите. Пример:
std::string_view sv = function_returning_string();
Тут string_view
будет dangling, потому что ссылается на временную строку, которая сразу будет уничтожена.
А если серьёзно, то C++ не хватает для умных указателей нормального синтаксиса.
Зачем писать std::unique_ptr<T>
, когда можно писать T^
?
Зачем писать std::make_unique<T>(...)
, когда можно писать new T^(...)
?
А лезть с синтаксическим сахаром в стандарт не нужно. Особенно с аргументацией «мне нравится unique_ptr, для его давайте схара, а остальные не надо, я ими не пользуюсь»
Только из за добавления сахара с++ стал юзабельным. С отвращением вспоминаю всё что было до с++03\с++11.
Необходимость синтаксиса для «умных» указателей это следствие наличия в языке:
а) Стандартного аллокатора, который по умолчанию используется для всего,
б) Деструкторов — суть и соль языка,
в) Собственно, необходимости работать с указателями.
new должен возвращять умный указатель на объект или блок памяни (начало и конец), иначе мы не далеко уходим от голимого Си.
new — часть языка, и для того чтобы язык выглядел более самодостаточным, было бы логичным что new возвращяет безопасный указатель, с однозначным намёком что этот указатель надо будет освободить, после использования.
struct MKSHARED
{
template<class T>
std::shared_ptr<T> operator*(T* ptr)
{
return std::shared_ptr<T>(ptr);
}
} MK_SHARED;
#define shared MK_SHARED*
auto p = shared new SomeClass();
auto v = unique new SomeClass();
struct T{};
T *operator^(T *lhs, T)
{
return lhs;
}
int main()
{
T x;
T *ptr = new T^(x);
}
Синтаксис C++ и так перегружен по части всевозможного использования закорючек — в стандарте в некоторых случаях приходится явно разрешать неоднозначность интерпретации тех или иных конструкций (например, является ли T() типом функции, возвращающей значение типа T, или созданием временного объекта типа T).
в стандарте в некоторых случаях приходится явно разрешать неоднозначность интерпретации тех или иных конструкций
Это следствие отсутствия ключевого слова "function".
Метки:
c++
c++20
1 апреля
В каждой шутке есть доля шутки. Указатели позволяют слишком много. Ссылки обрезаны по самое небалуйся. reference_wrapper имеет почти нужную семантику, но, как ни смешно, слишком длинное имя. А optional из стандарта не имеет sentinel value оптимизации, из-за чего проигрывает голым указателям и по размеру, и по совместимости. К тому же слишком "легко" превращается в голое значение. В общем не хватает чего-то вроде optional<ref<T>>
, имеющего почти нулевой оверхед по сравнению с указателем (за вычетом ассёртов в отладочном режиме).
Если вы про owned/notnull — они дают какую-то семантику только в паре со статическим чекером, который их понимает. Последний раз такой чекер был только в Visual Studio. Т.е. его работоспособность даже в VS Build Tools под вопросом. В целом же, как я вижу, С++ всё больше требуется отдельный независимый от компилятора DSL для описания статических проверок :)
AFAIK, тэги собирались удалять с Хабра (честно признаюсь: не ищу статьи по тэгам), но в данном случае тэги сыграли свою роль. Поэтому считаю что тэги на Хабре нужно оставить.
P.S. С прошедшими Днём Архивов и Днём Дураков!
Комитет, вместо проедания денег, лучше бы взялся за D — вот уж кому не помешали бы деньги и дополнительные ресурсы! Ди решил множество проблем Сипипей, но комитет старых пердунов продолжает насиловать стюардессу, год от года становясь всё более смешным.
www.youtube.com/watch?v=JfmTagWcqoE
Вот вышла краткая заметка о первоапрельском розыгрыше: Правда о "Указатели удаляют из C++".
Пять блогеров с разных уголков Земли договорились разыграть читателей в День дурака новостями об избавлении от указателей. Отклик на пять статей был гигантским, и растянулся от "давно пора!" до "это не может быть правдой!".
Все эти shared_ptr и unique_ptr просто в принципе не подходят для гейм-девелопмента.
unique_ptr ничуть не медленнее пары new/delete. Оверхед от shared_ptr в подавляющем большинстве случаев микроскопический в рамках приложения. Тем более что вы как сишник должны знать как часто в управлении временем жизни объектов на си используется тот же самый подсчет ссылок, что и внутри shared_ptr
Без new: Указатели будут удалены из C++