Перейти к содержанию
    

Стили оформления программ на C/C++ и их применимость

On 1/4/2024 at 8:34 AM, dxp said:

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

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

на питоне код лаконично выглядит а на плюсах нет - не тянет он на высокоуровневый и безопасным никогда не будет. Аналогичная zero-cost абстракция на раст

fn main() {
    let numbers = vec![100, 55, 80, 2, -1];
    let result: Vec<_> = numbers.iter()
        .filter(|&num| num % 2 == 0)
        .map(|num| num / 2)
        .collect();

    println!("{:?}", result);
}

 

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, mantech said:

 

2 hours ago, dxp said:

В-третьих, про 70-100 раз вы сами придумали? Тут "потери" могут быть только из-за алокации контейнера 

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

 

Вы похоже каждый о своем.

@mantech пишет про Python, а @dxp про C++

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очередная серия древнего холивара? 😄  Тушканчики против белочек, оливье против селедки под шубой, пельмени против котлет? 🙂 

А вы видели программы, писанные 1С-программистами? Ууу, там особая аура, особый коленкор 🙂 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 минут назад, EdgeAligned сказал:

А вы видели программы, писанные 1С-программистами? Ууу, там особая аура, особый коленкор 🙂 

К счастью нет, но слышал про такое)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 часов назад, mantech сказал:

ради текстовой компактности можно пожертвовать такими потерями в скорости

Нет никакой  "такой потери скорости". А зачастую есть именно выигрыш в скорости.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, VladislavS сказал:

Нет никакой  "такой потери скорости". А зачастую есть именно выигрыш в скорости.

В сравнении си и питона или си и плюсов?))))))

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 1/4/2024 at 9:16 PM, VladislavS said:

 А зачастую есть именно выигрыш в скорости.

 С чего бы вдруг ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Из опыта. Более совершенный инструмент позволяет писать более эффективный код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 часов назад, dxp сказал:

Многие участники форума, я видел, уже давно и успешно используют возможности C++11 (а может и 14), не испугались нововведений, хотя из-за них код программ местами сильно поменялся. 

И не дай Бог они уйдут или умрут - у тех кто будет продолжать проект будет наблюдаться вечный геморрой...

В 03.01.2024 в 13:20, jcxz сказал:

Ну например хотя-бы для того, чтобы можно было переменные объявлять где угодно. 

Да вроде и в Си можно объявлять где угодно, не забывая, впрочем о контейнерах ограниченных {}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, artemkad сказал:

И не дай Бог они уйдут или умрут - у тех кто будет продолжать проект будет наблюдаться вечный геморрой...

И что такого вечно-геморройного порождает С++11? Можно прям по пунктам пройтись.

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

2. nullptr. До этого использовался 0 или макрос NULL (что то же самое), иногда это вызывало проблемы -- например, при перегрузке функций. nullptr -- это специальный тип нулевого указателя, избавляет от указанных проблем, выразительность программы только выигрывает.

3. range-based циклы. Два примера:

int buf[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int sum   = 0;

// example 1
for(size_t i = 0; i < sizeof(buf)/sizeof(buf[0]); ++i)
{
    sum += buf[i];
}
            
// example 2
for(auto &i : buf)
{
    sum += i;
}

Какой вариант короче, проще писать и читать? Второй вариант является просто синтаксическим сахаром первого и натурально разворачивается в первый. При этом он универсальнее -- позволяет работать с контейнерами, используя итераторы. Там преимущество такой записи проявляется ещё больше. В частности, можно просто заменить массив на std::list<int>, и весь код остаётся прежним. 

Очевидное улучшение средств языка.

4. Ключевые слова override и final для лучшего контроля над методами (виртуальными функциями) в иерархиях классов. Позволяют избавиться от некоторого класса ошибок.

5. Строго типизированный enum. Вещь, которой мне всегда не хватало! Перечислимый тип в С -- это и не тип никакой, а просто способ создавать именованные литералы. В С++ сразу пошли чуть дальше: по крайней мере объектам типа enum нельзя было просто так присваивать левые значения -- инты, например. Но сами имена значений enum'а загромождали окружающее пространство имён -- всегда нужно помнить, что, например, константу с таким же именем уже не завести. А если пара enum'ов, описывающих состояния конечного автомата, в обоих есть по смыслу одинаковое состояние WAIT, то вот он и конфликт имён сразу же.

Строго типизированный enum закрывает эту проблему. enum class рожает значения своего перечислимого типа внутри себя. Если значение нужно использовать снаружи, то оно просто квалифицируется именем этого перечислимого типа, что нативно даёт читабельный и безопасный код.

Бесспорное улучшение языка.

6. Интеллектуальные указатели. unique_ptr, shared_ptr, weak_ptr. В значительной степени избавляет от необходимости вообще работать со свободной памятью. 

7. Лямбда-выражения. Звучит страшно. На самом деле -- это просто безымянный функтор (функтор -- класс/шаблон, у которого определён operator(), поэтому к нему можно применять операцию вызова, как функции -- () ). В С/С++ функции не являются объектами первого класса (т.е. с ними нельзя обращаться как с объектами в памяти, нельзя создать массив таких объектов), как, например, в языках типа Python или Lua (да почти во всех высокоуровневых языках), концепция функтора устраняет этот недостаток. Благодаря функторам можно делать всякие интересные штуки типа замыканий (closure -- захват контекста), а в качестве предикатов они вообще незаменимы. И это тот самый случай, когда некоторые C++ алгоритмы зачастую работают быстрее, чем их С аналоги -- например, алгоритм std::sort работает быстрее сишной qsort благодаря тому, что функция сравнения в std::sort может передаваться лямбдой, код которой инлайнится.

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

8. constexpr. Это вообще маст хэв штука. Особенно для ембеддед. Гарантирует, что значение объекта будет вычислено на этапе компиляции. В более поздних версиях стандарта (по-моему, в C++17) constexpr может использоваться в выражениях if для управления условной компиляцией

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 часов назад, dxp сказал:

Многие участники форума, я видел, уже давно и успешно используют возможности C++11 (а может и 14), не испугались нововведений, хотя из-за них код программ местами сильно поменялся. 

У меня С++17 в продакшене. Работаю с ARM, RISC-V и наследство AVR иногда всплывает. На С++20 делаю наработки на перспективу - код реально проще и надёжнее получается. От полного перехода останавливает только поддержка компиляторами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня тоже было предубеждение сначала. А потом меня товарищ подтолкнул в эту сторону, объяснив, что тот же С++17 -- это хорошо, он делает язык лучше: проще в использовании, безопаснее и более могучим по возможностям. Далее я только убедился в его правоте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 минуты назад, dxp сказал:

constexpr может использоваться в выражениях if для управления условной компиляцией

 

if constexpr это не условная компиляция в том виде как его С-шники понимают.. В этом месте ожидается/требуется выражение, которое будет вычислени на этапе компиляции. Оно будет скомпилировано по обоим веткам и в обоих случаях будет синтаксически проверено. А при инстанциации в код попадёт только нужная ветка. Причём они могут обе использоваться в зависимости от того как вызвали. В отличии от условной компиляции, где кусок кода просто выкидывается и его ни использовать, ни проверить на корректность нельзя.

 

42 минуты назад, dxp сказал:

Наверное, вспомнилось далеко не всё,

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

 

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

Ну там шаблонные лямбды с переменным количеством параметров код проще делают. Рэнжи и всё больше контейнеров в constexpr, хотя для эмбедда это не столь применимо. Модули пока чисто теоретически код лучше сделают, выхлопа от них я ещё не видел. Ну и т.д.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

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

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...