LINUX.ORG.RU

Продуктивность разработки на C++.

 , ,


6

12

Уважаемые программисты!

Предлагаю порассуждать о продуктивности разработки на C++ по сравнению с так называемыми скриптовыми языками. Вот, принято считать, что языки на вроде Python позволяют работать программисту более продуктивно по сравнению с C++. И что, дескать, на C++ надо писать только узкие места и всё такое.

Мне же хочется четкого понимания. Может быть это миф? А может быть это просто инерция, потому что так вот принято считать и все тут. Вот сегодня в C++ уже не надо думать об освобождении памяти, так как есть умные указатели. Сегодня есть уже более-менее нормальные IDE для C++. Так? Так.

Так что же тогда мешает писать на C++ столь же продуктивно, как на том же Python? Какие будут рассуждения? Может быть есть какие-то реальные обоснования на этот счёт, кроме как «в конторе Y так делают, значит смысл есть, они умные, им виднее». А может быть есть какие-то рецепты по продуктивности работы на C++?

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

Да. Нет.

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

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

А вот и отличная иллюстрация почему в C++ легко выстрелить в ногу. UB сам найдёшь?

Упс.

bool starts_with(const std::string& string, const std::string& pattern)
{
  return pattern.size() <= string.size() && std::equal(pattern.begin(), pattern.end(), string.begin());
}
Почему-то подумалось, что equal сверяет InputIterator2 с end(). Но, честно говоря, если бы я писал реальный код, то я бы сверился с документацией. Так что не могу согласиться, что это реальная проблема C++.

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

Почему Петросянство?

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

Не уж то нет библиотек, которые умеют парсить JSON одной строчкой кода? Мне просто лень искать, но что нереального я написал?

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

Т.е. в Python можно сделать проще?

parts = s.split()

Что-то не находится.

Вот и я о том же: ты не просто выстрелил себе в ногу, но и не можешь понять как несмотря на то что тебе на это явно указали. Хинт: что будет если pattern длиннее строки?

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

Почему-то подумалось, что equal сверяет InputIterator2 с end().

Каким ещё end()? Ты даже не знаешь языка который пытаешься защищать?

Но, честно говоря, если бы я писал реальный код, то я бы сверился с документацией. Так что не могу согласиться, что это реальная проблема C++.

Ты сейчас признал что на C++ нельзя писать без сверки с документацией, и при этом не считаешь это проблемой. Ok.

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

Либо только после изучения всей цепочки «железо-коды-асм-си-...»

C++ — это кроссплатформенный язык.

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

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

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

Ну в стандартной библиотеке нет парсера JSON. Это факт.

Смотри: тебе даже день посмотреть какие есть библиотеки для парсинга json, а разработчикам нужно посмотреть, сравнить, разобраться с API, поставить, подключить к сборке и протестировать на всех целевых платформах

Да пожалуйста. Вот я прям сейчас нашёл header-only библиотеку для JSON на C++ - https://github.com/nlohmann/json#examples:

// create object from string literal
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
Опять Петросянство?

Вот и я о том же: ты не просто выстрелил себе в ногу, но и не можешь понять как несмотря на то что тебе на это явно указали. Хинт: что будет если pattern длиннее строки?

Уже увидел. Спасибо.

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

Или прострелом ноги называется потенциальный крах приложения?

Ну да, тебе ж на UB указали

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

Ты сейчас признал что на C++ нельзя писать без сверки с документацией

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

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

Каким ещё end()? Ты даже не знаешь языка который пытаешься защищать?

С string.end(). Что значит не знаю? На определённом уровне я его знаю. Но это у всех так. И я его защищаю.

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

А на Python разве можно писать без сверки с документацией?

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

С pattern.end(). Что значит не знаю? На определённом уровне я его знаю. Но это у всех так.

Итератор по string с pattern.end()? Ну-ну.

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

На определённом уровне я его знаю. Но это у всех так.

Нет, и как раз, таким как ты, лучше брать какой-нибудь QtCore и использовать его вместо стандартной библиотеки. Будет почти как python.

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

string.end(), который ты не передал в вызов? Ну-ну.

А, ну да. Ну, бывает, короче. Но это бывает в любом языке и у всех. Или имеются объективные аргументы, что где-то такое не бывает?

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

Нет, и как раз, таким как ты, лучше брать какой-нибудь QtCore и использовать его вместо стандартной библиотеки. Будет почти как python.

Обоснуешь? А то я за подобными обоснованиями сюда и пришёл.

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

Ты сначала определи, что именно «бывает»

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

azelipupenko
() автор топика

Попробуй писать реальные программы на одном и другом. Хоть мелкие утилиты. А не офигительные вопросы задавай, чтобы пересказывались шаблоны про светлое будущее коммунизма.

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

Но это бывает в любом языке и у всех

Ну, это уже зависит не от языка, а от человека. И такое действительно бывает. Вопрос лишь в том, к чему это может привести в случае питона и C++

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

Попробуй писать реальные программы на одном и другом. Хоть мелкие утилиты. А не офигительные вопросы задавай, чтобы пересказывались шаблоны про светлое будущее коммунизма.

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

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

Вопрос лишь в том, к чему это может привести в случае питона и C++

В случае Питона это может привести к чему угодно, так же, как и в случае с C++. И то, что Питон не свалится в корку, ещё не говорит о том, что последствия от False-результата не приведут к чему-то ужасному. Это смотря чем управляет программа на Питоне. Так что опять же не всё так однозначно.

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

Или имеются объективные аргументы, что где-то такое не бывает?

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

А все объективные аргументы ты привёл сам - полез со второго раза искать и подключать внешнюю библиотеку (вместо import json), написал 5 строк неочевидного и крайне неэффективного кода на потоках (вместо .split()) и написал (опять таки) свою велосипедную функцию, в единственной строке которой допустил фатальную ошибку (вместо .startswith()). И это только три простейших примера.

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

В случае Питона это может привести к чему угодно, так же, как и в случае с C++

Не-а. Это не приведёт к тому, что ты запишешь в чужую память, например.

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

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

В случае Питона это может привести к чему угодно, так же, как и в случае с C++

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

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

крайне неэффективного кода на потоках (вместо .split())

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

https://github.com/tobbez/string-splitting

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

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

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

Ну, наверное, это так.

полез со второго раза искать и подключать внешнюю библиотеку (вместо import json)

Согласен, это контрпродруктивно, но я быстро нашёл библиотеку для JSON. Другое дело, насколько она качественна, будучи нестандартной.

написал 5 строк неочевидного и крайне неэффективного кода на потоках (вместо .split())

Неэффективного по сравнению с чем? Если ты про split() Питона, то я думаю, что мой код на потоках будет в сто крат эффективнее.

в единственной строке которой допустил фатальную ошибку (вместо .startswith())

Ну, это бывает везде.

Как бы там ни было, неужели на C++ продуктивными могут быть только киборги и/или гении, которые никогда не допускают ошибок?

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

поведение программы предсказуемо

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

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

Мы здесь не сравниваем производительность питона и C++.

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

Не-а. Это не приведёт к тому, что ты запишешь в чужую память, например.

Я о другом говорю. Допустим программа на Питоне управляет каким-нибудь жизненноважным аппаратом. И тут во время выполнения возвращается False, вместо True. Всё. жизненоважный аппарат работает не так, как надо. Ну и что толку от того, что сам Питон от этого не упадёт? Я об этом говорю, а не о UB в понимании записи в память.

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

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

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

неужели на C++ продуктивными могут быть только киборги и/или гении, которые никогда не допускают ошибок?

Нет, если ты не входишь в эти две категории, то тебе необходимо вручить тот же QtCore, например, запретить использовать голые указатели, влупить, например, clang-tidy в связке з git, и продуктивность будет вполне на уровне. У нас работают в том числе студенты, вполне себе справляются.

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

тебе необходимо вручить тот же QtCore, например, запретить использовать голые указатели, влупить, например, clang-tidy в связке з git, и продуктивность будет вполне на уровне.

То есть твой рецепт продуктивности на C++ - QtCore + clang-tidy + git?

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

Про эффективность речь не идёт. На rust, d, go будет в разы меньше кода с почти той же производительностью. И без граблей.

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

Это уже словоблудие не имеющее отношение к обсуждению.

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

Как бы там ни было, неужели на C++ продуктивными могут быть только киборги и/или гении, которые никогда не допускают ошибок?

Я уже писал что нужно чтобы писать на плюсах продуктивно. Но на самом деле это бессмысленный вопрос. Правильный вопрос - в каких случаях низкая продуктивность плюсов оправдывается большей эффективностью кода. И ещё хороший вопрос на что их заменить с увеличением продуктивности и без потери производительности.

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

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

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

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

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

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

На rust, d, go будет в разы меньше кода с почти той же производительностью. И без граблей.

Пилите Пишите, Шура, пишите.

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

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

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

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

Святая наивность. Компиляторы позволяют, а списки CVE только растут и растут, и фаззинг рулит.

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

Вы хоть читаете на что отвечаете?

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

Святая наивность. Компиляторы позволяют, а списки CVE только растут и растут, и фаззинг рулит.

Это как ездить на велосипеде и учить гонщиков F1 (авторов того же linux kernel) водить и указывать на их ошибки. Очевидно, что есть задачи, где писать опасный код просто необходимо. В том же коде на Rust полно unsafe, многие из них просто попрятали в стандартную библиотеку. Но все там за тебя не сделают, и если ты полезешь решать системные задачи, или даже многие простые, - ты везде накосячишь и с любым языком.

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

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

А кто тебе сказал, что он упал? Кривой код может просто похерить данные и продолжит работать. Простой пример, когда-то драйвер от nvidia радостно удалял /usr, используя «безопасный» sh.

anonymous
()

Тему удалить. Она завтра протухнет

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

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

Предсказуемость означает что программа делает то что написано в коде. Да, на питоне предсказуемо, на C/C++ нет.

Очевидно, что есть задачи, где писать опасный код просто необходимо.

Наверное ты хотел сказать «потенциально небезопасный». Очевидно, есть. Также очевидно, что тысячи уязвимостей находят в самом разном софте, где очевидно, не только нет никакой необходимости в небезопасном коде, но и явно нужна безопасность. Браузеры и openssl, например.

Но речь-то вообще была не об этом, а о твоём заявлении:

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

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

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

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

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

Я повторюсь: вы не читаете на что отвечаете, и пишете текст никак не связанный с обсуждением. Если у вас так туго с этим, формулирую максимально просто: определённые классы ошибок, возможные в C++, невозможны в питоне, обратное утверждение неверно.

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

В жизненноважном аппарате очень важно и то, насколько быстро ты исправишь проблему.

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

Предсказуемость означает что программа делает то что написано в коде. Да, на питоне предсказуемо, на C/C++ нет.

Кривая программа на С/С++ делает ровно тоже самое, что написано в коде. Сказали записать в левый адрес - будет сделано. И будет по этому адресу ровно то, что туда положили ранее. И точно так же в питоне похеренные данные могут проявиться не сразу, а через большой промежуток времени. И что в С++ с gdb + valgrind (если ранее не использовал санитайзеры), что в питоне с дебаггером, ты будешь пытаться поймать этот момент при отладке.

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

Очевидно ты просто не понял, что я написал.

https://clang.llvm.org/docs/AddressSanitizer.html https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

и пр. Вполне себе вариант, если не требуется максимальная производительность.

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

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

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

Я повторюсь: вы не читаете на что отвечаете, и пишете текст никак не связанный с обсуждением. Если у вас так туго с этим, формулирую максимально просто: определённые классы ошибок, возможные в C++, невозможны в питоне, обратное утверждение неверно.

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

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

И что в С++ с gdb + valgrind (если ранее не использовал санитайзеры), что в питоне с дебаггером, ты будешь пытаться поймать этот момент при отладке.

Как интересно. Несколькими сообщениями выше ты писал про «на руках ты имеешь только результат, не зная ни изначальных данных, ни имея возможности их повторить», а теперь уже gdb и valgrind доступны?

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

Очевидно ты просто не понял, что я написал.

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

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

Нет, это ты сводишь разные классы ошибок к сферической «порче данных» в вакууме, и делаешь вывод что она возможна во всех языках. Логично чо. Только если глаза разуть, то там где в C++ ты не попав в массив тихо изменил то что расположено за ним, и нашёл это только под valgrind, которого у тебя, как ты сам же сказал и так удобно забыл, может и не быть, в питоне ты получил исключение. As easy as that.

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