Комментарии 117
Так что я буду ждать с нетерпением С+=2)))))
cppfront и carbon как раз про это.
cppfront фактически делает апгрейд плюсов зашивая все механизмы GSL в язык, добавляя модули, обратную совместимость с плюсами и избавляя его от всякой дичи, типа спирали типов. В итоге всё это транспилируется в какой-то свежий С++ и в таком виде компилируется уже как обычно.
Про carbon не расскажу ибо у них компилятор не везде работает, но выглядит он в среднем не лучше какого-нибудь D.
Интересно, Карбон надо посмотреть.
А в чем ваши претензии к D? (у меня свои, сравнить )
Скажем, я не слишком фанат managed языков. Отдельное фе к именованию/code style, которое мне сильно напоминает Java. Можно ещё немножко поурчать про обманутые ожидания от флага -betterC. С другой стороны язык смог впитать заметное количество модных-молодёжных фич из других языков, так что разработчикам языка можно поаплодировать. В проде я это использовать конечно же не буду.
Наговариваете - он не менеджед, а нейтив, только что со сборщиком мусора, но можно и без него местами, что редкость для яп (@nogc) .
Ява в него транслируется, это да, все же он надмножество. Навязываемый код-стайл как то не видел, как и принудительного форматтера. Мог пропустить.
БеттерС без библиотеки это как голый король) Но ниша есть - CLI и embed.
Хорошие шаблоны, но использовать я тоже не стал, слишком был тогда волатильный синтаксис. И библиотек нужных не было.
Проще приспособиться к новым С++.
managed - это как раз языки с gc - кто-то управляет (manages) памятью в противовес ручному управлению (manual). вы просто пишите var x = blabla() и не думаете почистится ли память или нет. C#, Java, D, Python, Haskell - как раз из этой оперы. Можно включать /выключать всякие фичи языка и даже Java можно компилировать в aot/no gc, но зачем, если я могу не делая приседаний иметь все то же самое поведение по-умолчанию в C++/Rust/Odin/Zig. V на худой конец.
С — это процедурное программирование, а не функциональное. Функциональное — это про композицию, функции высшего порядка, ограничение побочных эффектов и прочие лямбды с монадами.
не мешайте людям считать любую программу с функциями функциональной. Среди программистов на питоне и джаваскрипте это доминирующее понимание функционального программирования
То есть автор хочет сказать, что API на Rust нельзя сделать неправильно? А на С++ - нельзя сделать корректным?)
Мне кажется пример с API не очень удачен. Проблема, имхо, не в конкретном языке, а в общем подходе к API как только к интерфейсу без поведения.
Я бы сказал пример крайне неудачен, ибо с большой вероятностью можно было б инкапсулировать половину этих методов и вообще не давать пользователю их вызывать.
Что-нибудь типа
using Shader = /* */;
ShaderRegistry{ /* */ };
class ShaderCompiler final{
std::vector<Shader> names;
friend ShaderRegistry Compile(ShaderCompiler&& compiler);
ShaderRegistry compile();
public:
// единственный доступный метод. Возвращает ссылку на себя,
// чтобы можно было вызывать цепочкой .add("asd").add("qwe")
ShaderCompiler& add(std::string_view name);
};
// можно поменять сигнатуру на какой-нибудь unique_ptr
ShaderRegistry Compile(ShaderCompiler&& compiler) {
// доступ к приватному методу есть только тут
return compiler.compile();
};
Ну, а проверку borrow checker пока ещё в процессе запиливания/стандартизации, так что пока не дожили.
Не так. Автор хотел, чтобы после вызова compile() вернулся уникальный экземпляр ShaderRegistry, причем очистился и сам ShaderCompiler.
Но пример неудачный, ибо потери производительности нет, и так будет RVO. А чистить надо было вручную.
Точнее, RVO будет для примера из статьи, у Вас хуже - будет копирование.
Даже такой вариант не защищает от использования переменной ShaderCompiler после передачи в метод Compile.
По идее компилятор должен выбрасывать исключение, если объект используется в перемещенном состоянии.
А что вы хотели от фаната руста, у которого задача просто обосрать плюсы? При желании можно было прям на поверхности найти кучу объективных недостатков у плюсов, которые не хотят фиксить, зато раз в 3 года выкатывают новые и новые эксперименты, которые хз когда появятся в реале (вот прямо тут жирный недостаток). Но автор решил пойти тупым путем. То ли плюсов не знает, то ли...
В С++ есть некая особенность, определяющая всё - это поддержка легаси кода.
А Rust'у до появления легаси ещё надо дожить :)
Может, если бы у C++ было больше времени, он стал бы лучше?
А он и так хорош!
Что меня умиляет в статьях авторов-теоретиков, что они не любят демонстрировать собственные проекты, где подтверждаются высказанные мим тезисы. Зато про «сферического коня в вакууме» могут говорить долго и с упоением.
Хорошо, возьмем собственные пет-проекты. Какой язык выбрать? Ведь, никто не принуждает и не навязывает своего авторитетного мнения. Только личные предпочтения. Для меня, это, однозначно, С++, по многим причинам. И даже, если результаты подвергаются критике (см. мои программы в https://habr.com/ru/articles/848836/ и http://scholium.webservis.ru/Pics/MediaText.png ), то это не повод переходить на другой язык, а, всего лишь, дополнительный интерес, искать решения на «старом, добром» С++. Например, главная претензия ко мне была в отсутствии «современного» интерфейса (имея в виду плоский интерфейс с чёрной темой, как, скажем, у Блендера). Ладно, посмотрел в этом направлении, нашел, разные варианты, с которыми разбираюсь. И, может быть, при достаточном желании, реализую его в следующих версиях.
Что-то я непонял перескок на чёрный UI как у Блендера.
Что-то я непонял перескок на чёрный UI как у Блендера.
Ну, я имел в виду интерфейс типа: https://erfaren.narod.ru/Pics/Blender.png . Или под «современным» интерфейсом понимается другой? Например, такой: https://erfaren.narod.ru/Pics/DuiLib.png ?
Так какая связь между стилистикой интерфейса, претензиям к интерфейсу и выбором ЯП?
Так какая связь между стилистикой интерфейса, претензиям к интерфейсу и выбором ЯП?
Никакой, естественно. Я говорю не о связи, а о своей реакции на претензии. Народ хочет «чёрную тему»? Ладно, смотрим, что можно предложить. Варианты есть, в рамках ранее выбранного С++. Пока, разбираюсь. Какие вопросы?
я говорил о множестве недостатков C++
ай, ну кто так ругает? детский сад.
30 years of single-minded search for uncompromisingly efficient and generic algorithms ended in shameful failure!
https://www.linkedin.com/pulse/do-you-still-trust-stl-sergey-derevyago-bzenf
Из за того что раст менее гибкий то и приложения на нем тормознутее, не?
Нет. Ограничение программисту даёт больше свободы [как обычно тупенькому] компилятору.
В теории, да и кстати на многих задачах benchmarksgame, Rust выигрывает. Если убрать сишные трики с интринсиками итп
Ага. Чем более ограничен программист - тем быстрее программы получаются?)
Эксклюзивность владения в Расте даёт сильные козыри для оптимизатора.
Нет, это ограничения совсем другого толка, не дающие никаких способов оптимизации. Единственное - в расте UB если есть 2 ссылки на одну память. Это даёт возможность где то незначительно оптимизировать, но эта оптимизация очень часто будет невалидной, потому что ситуация 2 ссылок на одну и ту же память очень часта
Напомню про сишный restrict, введенный исключительно для этой цели
так restrict не по умолчанию и там где это контракт функции, явно указываемый. А в расте это неявно и очень легко получить уб
Да и вообще, странно говорить "раст хороший - он убрал всё плохое что было в С++" и потом говорить "смотрите, у нас также как в С" (в С++ restrict нет)
Ну вроде как получить уб как раз не тривиально потому что сложно получить мутабельную ссылку пересекающуюся с другой ссылкой.
Но restrict по умолчанию только в safe Rust. А в unsafe мы оказываемся ближе к С (но не на его уровне), и можно писать код на указателях, главное при переходе снова к ссылкам соблюдать ограничение restrict.
На практике за этим надо следить разработчикам библиотек, которые что-то оптимизируют через unsafe и указатели, а в прикладном коде unsafe практически не встречается.
в прикладном коде unsafe практически не встречается.
Это только в пропаганде. В соседней статье про редактор, написанный в Микрософте на Расте есть ссылка на гитхаб. Посчитай сам количество ансейфов.
И такая картина везде, где я смотрел
Посмотрел. Похоже, что его транслировали из C в Rust (например этим), и потом добились того чтобы компилировался.
Я делаю такой вывод из того, что внутри написана реализация memset, memchr и юникода (лол). Так что ваш пример - это антипример.
P.S. Вот пример +- большого проекта (https://github.com/picodata/picodata), изначально написанного на Rust. На 112kloc Rust кода 238 строк unsafe (0.2%). Из них около 80% это плагин к tarantool, т.к. обращения к ffi.
Не похоже по коду, что это транспиляция. И об этом бы было написано, авторские производные права итп, корпорация же автор, строго.
memset просто там оптимизирован под SIMD, а юникод - биндинг к ICU (тут ансейф естествен)
Я вас прошу доказать вот эти ваши слова:
И такая картина везде, где я смотрел
Потому что вы широко заявляете про пропаганду, но как пример приводите маленький проект, и обобщаете его на все проекты на Rust.
А я вам привел большой контрпример на 112kloc. Теперь, если вы стоите на своем, докажите на нескольких (больших) проектах.
А зачем доказывать? Я же не утверждаю, что везде так.
Токио я смотрел, а что ещё так и не упомнишь. Где то всплыло в обсуждениях - ткнул полистал.
Как и ожидалось, фразу про пропаганду вам подкрепить нечем.
Неужели так сложно сказать "я погорячился / я ошибся"?
А, так вот о чем речь.... Так первичное утверждение было Ваше
в прикладном коде unsafe практически не встречается.
Вам его и доказывать.
Я привёл первый попавшийся контрпример)
А на Ваше "покажите большие проекты" я скажу - а проверим методом Монте-Карло.
Легко. Цитирую:
As of May 2024, there are about 145,000 crates; of which, approximately 127,000 contain significant code. Of those 127,000 crates, 24,362 make use of the
unsafe
keyword, which is 19.11% of all crates. And 34.35% make a direct function call into another crate that uses the unsafe keyword. 6 Nearly 20% of all crates have at least one instance of theunsafe
keyword, a non-trivial number.Most of these Unsafe Rust uses are calls into existing third-party non-Rust language code or libraries, such as C or C++. In fact, the crate with the most uses of the unsafe keyword is the Windows crate 7, which allows Rust developers to call into various Windows APIs.
Примерно 81% крейтов не содержат ни одной строчки unsafe. А среди остальных большинство - это FFI.
Теперь ваша очередь доказывать про пропаганду. Надеюсь получить аргументированный ответ.
Отлично, т.е 80% крейтов не нуждаются в ансейф. А поскольку речь шла о прикладном по, а не библиотеках, то в этой части должно быть и больше.
Теперь проверим моим способом. Открываем awesome rust, и из нейтральных приложений - не системных, не ffi, не игр, берём несколько наугад.
Например субд паритидб, смотрелка CSV, текстовый редактор, веб фрейворм поем
Я с телефона толком не поищу, смотрите самостоятельно много ли там ансейфа и обоснован ли он
1) parity-db 20/24600 = 0.081%
Внутри вызовы mmap и libс. Обоснованно.
Еще 3 transmute, на первый взгляд можно и без них.
2) tabiew 11/7252 = 0,15%
Всё в тестах, и абсолютно не нужно. Можно использовать static_cell или атомарные переменные.
3) xi-editor 30/29356 = 0.11%
sse, avx, libc - какие-то оптимизации.
Еще 2 не нужных str::from_utf8_unchecked.
4) poem 0/47700 = 0%
Если выкинуть ненужные (на мой взгляд) unsafe, выйдет (17+28)/(24600+7252+29356+47700) = 0.04%
В 2 из 4 проектах можно обойтись без unsafe точно.
P.S. mmap очевидно нужен, c libc, sse и avx я не разбирался, тут уже нужно много времени потратить.
Куда же вы пропали? Прошло уже 3 дня, на хабре вы бываете регулярно..
Я все еще жду от вас аргументации про пропаганду. Свой тезис я доказал общей статистикой, и вашим способом, по вашим же ссылкам.
Надеюсь на аргументированный ответ (но надежды уже тают..)
Так мы же закончили.
Программы без unsafe встречаются только в пропаганде (ладно, в поэм 0), но при правильном применении его очень мало. Если превышает некоторый процент порядка 0.1% кода, надо бы рефакторить.
Кроме того в поэм нашёл новую полезную прагму запрета ансейфа в конкретном файле. ![forbid(unsafe_code)]
Интересно вы по выборке из 4 приложений отменили общую статистику по всем крейтам (127,000 шт). Большая разница (25% vs 81%) должна была вам тонко намекнуть, что 4 шт для статистики ничтожны.
Вот статистика по строчкам кода из 4 приложений еще куда ни шло, т.к. обеспечена статистически значимым числом: суммарно 109000 строк кода.
Итого 0,04% обоснованного (или 0,05% всего) unsafe кода - это я и называю "в прикладном коде unsafe практически не встречается". Делайте выводы математически правильно!
Так я же сослался на математический метод. У меня образование позволяет.
Согласно нему, в 75% случаев ансейф встречается =). И то, я выборку в пользу его отсутствия делал.
Вообще метод описан, если Вам мала выборка из 4х, берите большую. Будет выше точность.
Ваше образование почему-то не позволило вам прочитать внимательно текст по вашей же ссылке:
Например, чтобы узнать методом Монте-Карло, какое в среднем будет расстояние между двумя случайными точками в круге, нужно взять координаты большого числа случайных пар точек в границах заданной окружности, для каждой пары вычислить расстояние, а потом для них посчитать среднее арифметическое.
4 штуки никак нельзя назвать большим числом. А вот 127,000 шт по моей ссылке уже большое число.
Кроме того, если в 4 крейтах будет 1/100000000000000000000000 строчек unsafe, по вашей статистике будет 100% случаев unsafe.
Встает вопрос, какие ещё допущения вам позволяет ваше математическое образование =)
P.S.
Вообще метод описан, если Вам мала выборка из 4х, берите большую. Будет выше точность.
С увеличением размера выборки до бесконечности (до фактического кол-ва крейтов) метод Монте-Карло превращается.. превращается в полноценную статистику, которую я уже приводил.
Кроме того, если в 4 крейтах будет 1/100000000000000000000000 строчек unsafe, по вашей статистике будет 100% случаев unsafe.
На 3й день индеец Зоркий Глаз заметил подвох =)
если руки неумелые, а если умелые?
----
Вообщем, можешь доказать, что програ в расте при одинаковом размере всегда быстрее за сишную?
А вся статья получается чистой спекуляцией на неоднозначности термина и поведения std::move()
В отличие от Раста, в плюсах мув семантика только семантика и не приводит к исчезновению переменной.
Всего лишь, способ подсказать компилятору о времени жизни, причём совет необязательный. Что и возмущает некоторых, Мэтров.
могу ошибаться пример с шейдером не понял,
значит есть статика, чтобы её рисовать, есть партиклы, есть анимации, 3 типа шейдеров, тоесть поидее должно быть 3 шейдера и вроде извините получается и на Алису и Боба 1 и тот же шейдер, потомучто надо просто пропустить модельку чтобы отрисовать и посветить на неё от игрока и источников, а ну еще шейдер сцены может быть (локация), + еффект(тоже тип шейдера), зачем на Боба и Алису создавать 2 разных шейдера, или я чото не понимаю
включаем сцену(
включаем Боба() + врубаем свечение() + врубаем партиклы на следы(бежать оставлять следы через дельту пропадать) + анимации()
)
итого выходит там будет 1 большой шейдер с выбором еффекта, партиклов, и анимации от Боба и Алисы (модельки в 1 таблице) и к моделькам можно применить еффекты, так же у моделек есть базовые индентификаторы уникальные, по которым понятно какие анимации и модельки по категориям подходят (аля большой справочник) так шейдер то сборный получается 1 а не 2 вроде при условии что Боб и Алиса 1 типового индентификатора
даже если они разные всё равно поидее 1 шейдер, туда вроде даже воду(морфом) засунуть можно-как еффект на локации и тапать её по индентификатору(но прогоняя как воду тоесть уже категория получается, но шейдер то 1 вроде)
тоесть другие категории это выбор елемента(уникальный тип взаимодействия), отрисовка 2д(новый тип отрисовки), ну и партиклы да наверно не засунуть в мейн шейдер, но 1 шейдером можно пол локации вроде отрисовать, при условии что он собирается перед компиляцией(софтовый include, это исключение повторов тогда внутри такого шейдера будет условие выбора отрисовки по типу, времени или еще как)
Все описанные в статье проблемы проистекают из модели работы C++. Там невозможно деструктивное перемещение, ибо любое изменение расположения класса в памяти должно проходить через конструкторы или операторы присваивания. Нужно это якобы для поддержки случаев, когда в классе ссылки на его члены хранятся и чтобы при перемещении эти ссылки было скорректированы. На самом деле так мало кто делает, но в раз в стандарте прописано, то менять этого нельзя.
Опять пиарщики Раста воюют с недостатками плюсов 15-летней давности
Отлично, то есть спустя 15 лет они всё-таки были исправлены! Исправлены, да?..
Достоинство Раста в том, что он не даёт наделать ошибок при работе с памятью. Откуда возьмутся такие ошибки в С++, если на нём писать как на С++, а не как на С?
Обычная пиар-статья Раста это "давайте рассыпем по коду сырых указателей да наворотим дикой дичи в стиле pure C".
Откуда возьмутся такие ошибки в С++, если на нём писать как на С++, а не как на С?
Да хотя бы из-за невнимательности программиста. Сохранить где-то ссылку на временную переменную, которая протухает при выходе из скоупа -- как два байта. Вы запросто это можете получить даже на обычном std::max.
А вы точно прочитали статью? В конце раздела На сцене появляется C++11 ровно один указатель, и можно было бы заменить на std::string без изменения сути примера.
А суть в том, что на повторный std::move компилятор не выдает ошибку (и даже варнинг), и нужно много приседать, чтобы компилятор что-то заметил. Ито это не гарантируется.
"давайте рассыпем по коду сырых указателей да наворотим дикой дичи в стиле pure C".
Статью не читали, но осуждаете да?
что на повторный std::move компилятор не выдает ошибку
А почему должен? Стандарт не запрещает move-from больше одного раза.
Я считаю что это ошибка дизайна стандарта, и автор статьи тоже пытается это показать на примерах.
Причем не могу придумать ситуацию, где бы это было полезно. А значит можно было бы и поменять в новых версиях стандарта.
Господа минусующие, не могли бы вы аргументировать свою позицию?
Так у вас у самого тут нет никакой аргументации. "я считаю" — а другие считают иначе. Второй абзац просто смешной, такое вообще странно слышать от человека, причастного к айти: ведь как хорошо известно, значительная доля проблемности всевозможных переделок не в том, что кому-то лень сделать лучше, а в том, что сложно гарантировать, что не станет хуже.
Аргументация в самой статье, о чем я и написал. Но в комментариях до моего первого поста суть статьи почти не обсуждали.
Менять же можно разными способами: добавляя новые ключи компиляции, внести в один из профилей безопасности и т.д. А старый функционал постепенно объявлять deprecated.
А теперь посмотрите, на мой первый пост. Минусующие (и вы тоже) даже не поняли, что я знаю как работает std::move по стандарту, и критикую именно стандарт. А заминусовали за то, что я как-бы не знаю стандарт.
Потому что повторный move приводит к UB, что может быть использовано в качестве уязвимости. Не слишком обнадёживающее поведение.
С чего бы оно должно к нему приводить? Стандарт прямым текстом говорит, что moved-from объект остаётся в unspecified but valid state (emph. mine). move из объекта, находящегося в валидном состоянии, сам по себе не UB.
Не, оно конечно возможно (и даже совсем-совсем не сложно) написать такой код, который будет UB при двойном муве, но это нужно сделать специально. Не делайте :)
Не делайте :)
Собственно, люди хотят, чтобы компилятор говорил это ровно в тех ситуациях в которых описано выше. Но он не говорит и молча компилирует. Ну и когда флаги оптимизации включаются там тоже можно отдельных приколов огрести, когда поведение внезапно начинает меняться.
(и даже совсем-совсем не сложно
ну и вот это как раз и проблема - есть ненулевой шанс написать такой код случайно.
сам по себе не UB.
специально не расшифровывал UB, т.к. их два штуки - unspecified behaviour и undefined behavior. Первое как раз про двойной мув.
специально не расшифровывал UB, т.к. их два штуки - unspecified behaviour и undefined behavior. Первое как раз про двойной мув.
Двойной мув допустим, просто в зависимости от применения, можно получить второй раз пустой объект.
Unless otherwise specified, all standard library objects that have been moved from are placed in a "valid but unspecified state", meaning the object's class invariants hold (so functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from):
Прямая цитата, наверное правильнее будет.
Он не пустой, он "valid but unspecified state". То есть стандарт гарантирует, что такой код считается валидным, что вызов функции или запись в объект новых данных не приведёт к падению программы, однако гарантировать поведение оно не даёт, т.к. оно зависит от компилятора, флагов оптимизации и какой-нибудь фазы луны. В каких-то ситуациях оно действительно будет превращено в нули, в каких-то объект "перемещённый" останется на месте в памяти и будет действовать как будто объект никуда не перемещался, в каких-то оптимизация превратит обращение к объекту в nop
и дальнейшие манипуляции станут бесполезными. Все эти нюансы как раз и есть unspecified behavior, которые придётся тестировать самостоятельно/ Если вас устраивает наличие UB и вы его как-то даже эксплуатируете - отлично, только это определённо не общий случай, на который нацеливается язык.
Стоит отдельно отметить, что это делает на сам move(), а присваивание или конструирование с ним. Сам мув ничего не делает.
И зависит поведение не от опции компилятора, а от документированного (или нет) вызова этого самого конструктора перемещения.
Конечно это непереносимый между компиляторами код в случае STL, но называть это UB все же вносит путаницу. Ошибки памяти само по себе это не даст.
Собственно, люди хотят, чтобы компилятор говорил это ровно в тех ситуациях в которых описано выше.
Компилятор (по крайней мере плюсов) не способен в принципе отделить мув, который не приведёт к UB, от мува, который приведёт к UB. Либо резать всё, либо ничего.
есть ненулевой шанс написать такой код случайно
Есть ненулевой шанс получить облицовкой по голове, но в строительных касках никто не ходит.
std::string_view<char> foo(std::string str) { return str; }
Вот идиоматичный C++11 код, который приводит к use after free.
Тут нет ничего идиоматичного (не говоря уж про то, что это не C++ код (и не потому, что UB)).
не говоря уж про то, что это не C++ код
И какой же это код? Неужели Си-шный?
И какой же это код?
Неправильный, вестимо
И не сишный тоже.
Неправильный, вестимо
Т.е. если код написан на C++, но оказался неправильным, то это не C++ код?
Ой, как удобно!
И даже смешно, что критик не осиливает 1 строчку кода без ошибок написать =)
Вообще есть в стандарте - the program is ill-formed; no diagnostic required.
Писал с телефона, уж извиняйте. Максимум что здесь выдаст компилятор это предупреждение, но никак не ошибку. А предупреждения можно и случайно отключить...
И даже смешно, что критик не осиливает 1 строчку кода без ошибок написать
Про какую именно ошибку речь? Про то, что нет string_view<char>
?
Ну так в комментариях никто не обязан сходу писать компилирующийся и линкующийся код. Можно считать, что там написано либо:
std::basic_string_view<char> foo(std::string str) { return str; }
либо
std::string_view foo(std::string str) { return str; }
суть это не меняет.
Вообще есть в стандарте - the program is ill-formed; no diagnostic required.
В стандарте много чего есть, но как-то оно не сильно помогает писать код без ошибок.
Чтение документации и учебников таки помогает писать код без ошибок.
В каком-то учебнике есть положительный пример возврата стрингвью?
Я, например, могу ткнуть пальцем в МС лёрн, где написано, как его применять.
Чтение документации и учебников таки помогает писать код без ошибок.
Только вот это необходимое, но недостаточное условие.
В каком-то учебнике есть положительный пример возврата стрингвью?
А вы програмируете только так, как написано в учебнике?
Однако, у вас есть нехорошая привычка не отвечать на вопросы. А именно:
Про какую именно ошибку речь?
std::string_view было бы правильно для компилятора .
Но неправильно применено.
Зачем писать очевидные ответы ?
std::string_view было бы правильно для компилятора .
Ну вот как раз std::string_view<char>
-- это неправильно для компилятора, т.к. std::string_view -- это псевдоним для std::basic_string_view<char>
, этот псевдоним не может быть чем-либо параметризован.
Но неправильно применено.
Так именно в этом и смысл примера: код, на который компилятор не ругается, но который является принципиально ошибочным. И эта та самая ошибка памяти, о якобы невозможности которой здесь выше кто-то заикнулся.
И да, это как раз таки ошибка памяти, хоть вы так и не считаете:
Если начать с начала этой ветки комментариев, или даже самой статьи,то можно заметить, что ошибок памяти тут нет.
После таких заявлений мнение "экспертов" можно сходу отправлять в /dev/null.
Зачем писать очевидные ответы ?
Как раз в данном случае было более чем не очевидно. Но стало очевидно, что в предмете вы не разбираетесь, однако мнение имеете.
Во-первых. Стрингвью притащили в комментариях и в другой ветке. В статье его нет. Upd. Ладно, ветка эта же.
Во-вторых. В глупом примере со стрингвью ошибка памяти после исправления есть, и компилятор на неё даже ругается.
Упд, ладно, я тоже ветки попутал. Взаимное недопонимание.
Во-первых. Стрингвью притащили в комментариях и в другой ветке.
Ну так посмотрите к какому именно комментарию был дан ответ с примером со string_view: https://habr.com/ru/articles/913702/comments/#comment_28373696
Увидите, что к тому самому, в дочерних к которому мы сейчас и находимся.
В статье его нет.
А никто и не говорил, что он есть в статье.
Некто @dv0ich заявил буквально следующее:
Откуда возьмутся такие ошибки в С++, если на нём писать как на С++, а не как на С?
И ему дали пример того "откуда возьмутся". Я бы и сам примеров накидал, но было лень в 100500-ый раз повторять очевидное.
Во-вторых. В глупом примере со стрингвью ошибка памяти после исправления есть, и компилятор на неё даже ругается.
Правда? Да что вы говорите!
https://godbolt.org/z/G1fKf9ss1 -- покажите пальцем на ошибку от компилятора, плиз.
main.cpp:7:10: warning: address of stack memory associated with parameter 'str' returned [-Wreturn-stack-address] { return str; } ^~~
Годболт с телефона глючит, это в cpp.sh, там по умолчанию
Warnings
Many (-Wall)
Extra (-Wextra)
Pedantic (-Wpedantic
Но это без - fanalyzer
Про ветку комментов я ошибся, исправил)
Ну вот вам еще godbolt для gcc 14.3 с -Wall -Wextra -Wpedantic
: https://godbolt.org/z/q7TEdvc3x
Не ругается.
Аналогично с wandbox: https://wandbox.org/permlink/rYq6VFom5zNtmzYt
Нет ни ошибок, ни предупреждений.
Более того, реальных проектов, где использовались бы -Wall
и -Wextra
не так уж и много. Просто потому, что в реальных проектах используются сторонние либы, а их авторы не заморачиваются на то, чтобы код компилировался без предупреждений на высоких уровнях. Да и слишком накладно достижение этого, особенно если нужно поддерживать и gcc, и clang, и msvc. Достаточно подключить в проект asio или fmtlib, чтобы получить кучу предупреждений при наличии -Wall
.
Ну и главное: пример-то тривиальнейший, не так уж сложно сделать пример, в котором наивный анализ от компилятора ничего не выявит.
Расследование показало, что cpp.sh использует clang, и на годболте тоже ошибку он видит.
Насчет ошибок памяти тут я не согласен ни с шапкозакидательским ни с Вашим утверждениями.
По моему, в С++ давно идёт борьба со скрытыми программисткими ошибками в области надежности, но граблей остаётся предостаточно.
И, сначала надо прочитать учебники, гайдлайны, стандарт только для сокращения количества ошибок.
И все равно, компилятор вас спасать не особо собирается.
Расследование показало, что cpp.sh использует clang, и на годболте тоже ошибку он видит.
И? Есть широко используемый компилятор, который не видит. Сделать пример, в котором и clang не будет видеть не проблема от слова совсем.
По моему, в С++ давно идёт борьба со скрытыми программисткими ошибками в области надежности, но граблей остаётся предостаточно.
Вы это автору тезиса про "Откуда возьмутся такие ошибки в С++, если на нём писать как на С++, а не как на С?" объясните.
И, сначала надо прочитать учебники, гайдлайны, стандарт только для сокращения количества ошибок.
Вот честно, складывается ощущение, что вы уже забыли когда в последний раз писали код. Ибо если бы вы это делали, то знали бы, что есть огромное количество ошибок, допущенных по невнимательности (да тех же опечаток), от которых не спасает штудирование учебников/гайдлайнов/стандартов.
Тогда как принципиальные ограничения языка (как в Rust-е, скажем), от некоторого процента таких ошибок защищают. В отличии от C++.
Что касается якобы моего утверждения, то оно относилось только к тому, что C++ не обещал решить все проблемы работы с памятью из Си.
Мне кажется, Вы слишком категорически трактуете моё выражение "граблей остаётся предостаточно" и "сокращение количества ошибок" как полное избавление от них =) итд
Раст на мой взгляд ближе к тому подходу, что "если запретить автомобили, ДТП не будет"
А как должен выглядеть идиоматичный для данного примера?
Проблема в том что до сих пор C++ это по большому счету сахар над C, как здесь, отдельно std::string и std::string_view написаны на языковых конструкциях C++, но связываются они по сути через C модель работы с памятью.
А как должен выглядеть идиоматичный для данного примера?
Проблема в том что до сих пор
В необразованности проблема.
Идиоматические примеры написаны в учебниках. Приятной учёбы.
Остальную чушь Я даже комментировать не буду, см п1
> как должен выглядеть идиоматичный
std::string foo(std::string str) { return str; }
То, что плюсы можно использовать в режиме "си с классами" не делает его сахаром.
С++ — это, конечно, существенный шаг вперёд по сравнению с С, но всех проблем работы с памятью он не решает. Например, с инвалидацией итераторов или многопоточным доступом. Иначе и Rust не появился бы.
Ну всех проблем никто не решает.
Везде какой то баланс цены, удобства за частичное решение.
С++ — это, конечно, существенный шаг вперёд по сравнению с С, но всех проблем работы с памятью он не решает.
Так он и не собирался это делать.
Когда я думаю о комитете C++, то представляю группу людей, усиленно старающихся сделать так, чтобы новые фичи было сложно использовать корректно и создать при этом максимальное количество ловушек.
И если уж я начал: комитет по стандарту, пожалуйста, дайте нам качественный строковый тип и срезы с проверкой границ.
А по мне, так и есть. Рассуждаю как человек, который не постоянно использует С++ - невозможно в голове держать все эти ловушки, если постоянно не сидишь в С++ 100% времени. Выкручиваюсь тем, что минимально использую фичи, что-бы потом не думать - это ошибка у меня в коде или я просто что-то не так понял в стандарте, с его квестами и ребусами. Жаль, С++ - сам по себе нравится.
Можно использовать похожие языки, если нравится синтаксис. Выбрать наиболее подходящий под задачу. Их есть
Собственно, не использовать многие фичи до полного их понимания тоже вариант. Тем более, что они зачастую служат только для повышения производительности, а преждевременная оптимизация - зло. И без них С++ быстрее очень многих
Встраиваемые системы - какие там другие, кроме С/С++. Последнее время Rust рекламируют, но у меня пока не настолько всё плохо, в моем случае, что-бы его изучать, он всё-же чуть другой, значит нужно дольше разбираться и если не пишешь каждый день - будешь забывать тонкости Rust, т.к. всё-же он чуть другой по логике.
в С++ сейчас много Чудовищного... но выход есть!
все еще можно легко и красиво, когда выбросишь чепуху:
предупреждаю: Ваш взгляд на Мир C++ уже не останется прежним!
Дело в том, что я нашел изящное решение Большой Проблемы. Но оно сотрясает Основы...
https://ders.by/cpp/norefs/norefs.html
Не люблю минусовать комментарии и стать на Хабре, но ваши комментарии этого таки заслуживают.
Он этакий луддист от мира С++ =)
Пока что больше похоже на то, что он ведет себя как Д'Артаньян, который весь в белом один стоит красивый, а остальные все в известной субстанции (особенно разработчики C++ и стандартной библиотеки C++). Ему бы отдельную статью на Хабре написать с основными тезисами своих изысканий, и уже оттуда бы давать ссылки на свой сайт со своими работами. Чтобы было отдельное место где автору объяснили бы в чем он не прав (если бы нашлись желающие).
Если честно, вся эта эпопея с продвижением одних языков через нахождение в других фатальных недостатков уже несколько приелась.
Ну и во-вторых, выбор языка зачастую обуславливается не хотелкой левой пятки программиста, а требованиями бизнеса, доступными под архитектуру компиляторами и традициями конкретной конторы. А в пет проекте хоть на brainfuck пишите, если он нравится.
Может, если бы у C++ было больше времени, он стал бы лучше?