LINUX.ORG.RU

Может кто нибудь показать красоту с++?

 ,


7

9

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

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

Мне кажется, что тут дело не в шаблонах, а в том, что в prog2 тела методов реализованы внутри классов, что делает их inline

Определение функции-члена шаблона класса вне определения шаблона класса, не даст ровным счётом ничего, поскольку в каждой единице трансляции оно будет компилироваться снова и снова, будь оно хоть инлайн, хоть не инлайн. На это можно было бы уповать, если б компиляторы поддерживали реализацию export, но они не осилили. (Теперь export будет использоваться в модулях.) Но даже export бы не помог в данной ситуации, т.к. print_info() шаблона Variant зависит от параметра шаблона, поэтому сколько будет вариаций Variant<T>, столько будет и вариаций print_info(). А вот print_info() не шаблона Variant представлена в единственном числе.

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

что не так со стилем?

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

Имхо, это уже проблема читающего.

Неважно, чьей проблемой ты это считаешь. Стиль - твой.

А почему чушь?

Читать здесь: http://en.cppreference.com/w/cpp/string/basic_string

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

Риторический вопрос вообще на смысл не влияет.

Своим произведением автор хотел сказать, что...

i-rinat ★★★★★
()
Ответ на: комментарий от tailgunner

Читать здесь

Но про буфер в 15 байт, спрятанный в std::basic_string, там не написано.

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

На это можно было бы уповать, если б компиляторы поддерживали реализацию export, но они не осилили.

Да, сорри, перепутал export с extern. :-)

А вот print_info() не шаблона Variant представлена в единственном числе.

Тоже верно.

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

Тоже верно.

Вы продолжаете обсуждать что? Что смайлодаун не смог вызвать strip и сделал на основании этого какие-то далекоидущие выводы?

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

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

что не так со стилем?

Такое впечатление

Имхо, это уже проблема читающего.

Неважно, чьей проблемой ты это считаешь. Стиль - твой.

А впечатления — твои. Я же тебя про мой стиль спрашивал, а ты вместо этого — про свои впечатления. И при чём тут мой стиль?

А почему чушь?

Читать здесь: http://en.cppreference.com/w/cpp/string/basic_string

Т. е. ты предлагаешь на 100 статических строк типа string создать 100 аллокаторов? Ещё лучше. А главное — удобно и компактно.

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

Я же тебя про мой стиль спрашивал

Я тебе про него и ответил.

Читать здесь: http://en.cppreference.com/w/cpp/string/basic_string

Т. е. ты предлагаешь на 100 статических строк типа string создать 100 аллокаторов?

Нет. Читай еще.

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

Вы продолжаете обсуждать что? Что смайлодаун не смог вызвать strip и сделал на основании этого какие-то далекоидущие выводы?

Ты просил доказательств, что шаблоны дуют код. Ты думал, что тебе их не представят, а сольются. Но тебе они были представлены. Ты сделал strip и всё равно получил разницу в 8 байт. Доказывает ли это, что шаблоны дуют код? Да, доказывают. Удалось ли тебе доказать обратное? Нет, не удалось.

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

Ты сделал strip и всё равно получил разницу в 8 байт. Доказывает ли это, что шаблоны дуют код? Да, доказывают.

На одном тестовом примере продемонстрировано «раздувание» на 0.1%. Отличное доказательство.

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

Ты думал, что тебе их не представят, а сольются.

Вы еще попробуете рассказать мне о чем я думал? Может ваше скудоумие отягощено и шизофренией?

Ты сделал strip и всё равно получил разницу в 8 байт. Доказывает ли это, что шаблоны дуют код? Да, доказывают.

Я бы больше сказал: очень убедительно доказывают. Очень.

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

На одном тестовом примере продемонстрировано «раздувание» на 0.1%. Отличное доказательство.

Да хоть на 0.0001%. Шаблоны дуют код. И это доказано.

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

Шаблоны дуют код. И это доказано.

Не доказано, а продемонстрировано. И продемонстрированная величина «раздутия» показывает, что ее можно не принимать во внимание.

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

не смог вызвать strip

Кстати, да, как ни странно.

$ ls -nl prog1 prog2 prog3 prog11
-rwxr-xr-x 1 1000 999 14864 фев 25 13:25 prog1
-rwxr-xr-x 1 1000 999 14992 фев 25 13:38 prog11
-rwxr-xr-x 1 1000 999 14936 фев 25 13:25 prog2
-rwxr-xr-x 1 1000 999 14936 фев 25 13:31 prog3

$ for i in prog1 prog2 prog3 prog11; do strip $i; done

$ ls -nl prog1 prog2 prog3 prog11
-rwxr-xr-x 1 1000 999 11664 фев 25 16:36 prog1
-rwxr-xr-x 1 1000 999 11664 фев 25 16:36 prog11
-rwxr-xr-x 1 1000 999 11664 фев 25 16:36 prog2
-rwxr-xr-x 1 1000 999 11664 фев 25 16:36 prog3

Как ни странно, размеры всех эльфов совпадают до байта, хоть я и не могу понять — почему, ведь и число функций в разных вариантах различается, и наличие/отсутствие inline. azelipupenko, похоже, мы неправы.

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

Не доказано, а продемонстрировано.

Доказано опытным путём. Прямо как на спортивных соревнованиях.

И продемонстрированная величина «раздутия» показывает, что ее можно не принимать во внимание.

Доказано что шаблоны дуют код в принципе. Величина «раздутия» будет зависеть уже от конкретного проекта. В показанном хеллоуворлде эта величина равно 8 байтам. Не в хеллоуворлде такая величина может быть будет и под мегабайты.

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

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

Я же тебя про мой стиль спрашивал

Я тебе про него и ответил.

Нет, ты про свои впечатления говорил. Вот определение стиля:

СТИЛЬ Мужской род 1. Характерный вид, разновидность чего-н., выражающаяся в каких-н. особенных признаках, свойствах художественного оформления. «Русский национальный с. в искусстве» 2. Метод, совокупность приёмов какой-н. работы, деятельности.

И про впечатления ни слова.

Читать здесь: http://en.cppreference.com/w/cpp/string/basic_string

Т. е. ты предлагаешь на 100 статических строк типа string создать 100 аллокаторов?

Нет. Читай еще.

Так приведи цитату, и я прочитаю.

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

Как ни странно, размеры всех эльфов совпадают до байта, хоть я и не могу понять — почему, ведь и число функций в разных вариантах различается, и наличие/отсутствие inline.

У меня GCC 7.2.0. Вот результат strip:

-rwxrwxr-x 1 1000 1000 6800 фев 25 16:48 prog1
-rwxrwxr-x 1 1000 1000 6808 фев 25 16:48 prog2

azelipupenko, похоже, мы неправы.

Не похоже.

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

В таких машинах и 8 байт - не мало.

Мне кажется, что это всё-таки преувеличение. Ну да, могут быть устройства, где каждый килобайт важен. Но 8 байт... разве что всё делается впритык. Но так делать нельзя, ведь стоит сменить компилятор или чуть-чуть изменить код, например, исправив баг, и он уже может не запуститься. А значит, всерьёз говорить о 8 байтах даже на самой слабой технике не приходится. А если есть такая техника, то там нужен asm, а не си.

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

Мне кажется, что это всё-таки преувеличение.

Знаешь такое выражение: курочка клюёт по зёрнышку, а весь двор засерает? Вот это тот самый случай.

Не надо цепляться к конкретной величине 8 байт. Надо просто понимать, что шаблоны не бесплатны, как некоторые любят привирать.

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

У меня GCC 7.2.0. Вот результат strip:

А у меня 7.3.0. Значит, многое зависит ещё и от версии, даже если разница всего в 0.1. Кстати, странно, что у меня при таких же опциях настолько жирнее код. У тебя, наверно, 32-битный компилятор?

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

Вот определение стиля:
Характерный вид, разновидность чего-н., выражающаяся в каких-н. особенных признаках

Главный признак твоего стиля здесь: Может кто нибудь показать красоту с++? (комментарий)

Так приведи цитату

Цитату из чьих слов?

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

Главный признак твоего стиля здесь: Может кто нибудь показать красоту с++? (комментарий)

Это не признак стиля, а твоё впечатление. Например, если аналогичное впечатление у тебя вызовет «Евгений Онегин», это совсем не будет характеризовать его стиль. Равно, как если на тебя не произведёт впечатление «100 лет одиночества», это никак не характеризует стиль и достоинства этого романа. Стиль — вещь относительно объективная (с определёнными оговорками), твоя же ремарка абсолютно субъективна и бездоказательна. И, разумеется, ни с Пушкиным, ни с Маркесом я себя не сравниваю.

Так приведи цитату

Цитату из чьих слов?

Цитату или пример, показывающие, как сделать 100 строк типа string, каждая из которых находится по своему фиксированному (а не динамически выделяемому, пусть даже в статическом буфере) адресу памяти без создания сотни аллокаторов.

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

У тебя, наверно, 32-битный компилятор?

Нет, 64.

Странно. Неужели версия 7.3.0 так раздувает код? Ведь и примеры (кроме 2 своих дополнительных), и опции компиляции я скопипастил.

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

Главный признак твоего стиля здесь: Может кто нибудь показать красоту с++? (комментарий)

Это не признак стиля,

«Особенный признак, свойство» твоего изложения - вызывать описанное выше впечатление. Такова твоя индивидуальная манера изложения.

Так приведи цитату

Цитату из чьих слов?

Цитату

Еще раз - цитату из чьих слов?

пример, показывающие, как сделать 100 строк типа string, каждая из которых находится по своему фиксированному (а не динамически выделяемому, пусть даже в статическом буфере) адресу памяти

Ааахренеть. Зачем? О чем ты вообще?

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

«Особенный признак, свойство» твоего изложения - вызывать описанное выше впечатление. Такова твоя индивидуальная манера изложения.

Нет. Такова твоя индивидуальная манера восприятия.

Еще раз - цитату из чьих слов?

Из чьих хочешь. Хоть бы даже и отсюда: http://en.cppreference.com/w/cpp/string/basic_string

пример, показывающие, как сделать 100 строк типа string, каждая из которых находится по своему фиксированному (а не динамически выделяемому, пусть даже в статическом буфере) адресу памяти

Ааахренеть. Зачем? О чем ты вообще?

Я напомню нить разговора:

Я тоже не заметил, что в си варианте используется статический буфер. Но справедливости ради надо сказать, что хотя формально сравнение и некорректно, но при работе с массивом char и традиционными си-функциями всегда можно выбрать то, что лучше подходит. А вот при работе с std::string и QString выбора нет. И это тоже серьёзный недостаток, если говорить о гибкости и производительности.

Какой стиль! И какая чушь.

А почему чушь?

Читать здесь: http://en.cppreference.com/w/cpp/string/basic_string

Т. е. ты предлагаешь на 100 статических строк типа string создать 100 аллокаторов?

Нет. Читай еще.

Т. е. мою реплику о том, что массивы типа char гибче string в том плане, что они могут быть и динамическими, и статическими, и на стеке, ты назвал чушью и послал меня читать cppreference.com. Там я ничего, кроме упоминаний аллокаторов, в поддержку твоих слов не нашёл и попросил дать мне конкретную цитату или пример, которую (который) ты имел в виду.

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

В том, что тот код, который якобы медленнее, на самом деле выполняет совсем другую задачу.

Но какую задачу он выполняет, кроме складывания символьных цепочек?

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

Такова твоя индивидуальная манера восприятия.

Ну да, ну да. Можно еще испортить воздух и вещать манере восприятия. Впрочем, как скажешь.

Еще раз - цитату из чьих слов?

Из чьих хочешь.

Да? Ну окей: " — Разве же я употребляю? — услышал Кейс, продираясь сквозь толпу к «Тацу».—Просто у моего организма острая алкогольно-наркотическая недостаточность".

Люблю эту цитату.

Я напомню нить разговора:

Разговора? Был (риторический) вопрос: Может кто нибудь показать красоту с++? (комментарий). Твой вклад в этот разговор - объяснение, что такое стиль, и фантазии об аллокаторах и фиксированных адресах. Ну а после этого Может кто нибудь показать красоту с++? (комментарий) очевидно, что ты некомпетентен примерно полностью.

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

переполнение signed int - максимальное значение знаковой i меньше максимального значения беззнакового size, соотв. в ситуации когда size достаточно велик, будет UB

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

Но только я читал (сам, правда, не тестировал), что строки и другие классы Qt по скорости уступают аналогичным из STL. Брехня или нет?

Два момента:

* QString в обязательном виде хранит строку в UTF16, на системах отличных от Windows (и отчасти macOS) это практически никогда не соответствует кодировке в которой данные принимаются или передаются. Но выгодно для отрисовки текста (так как надо засунуть строку в Harfbuzz) и для перекодировки (ICU)

* QByteArray тоже поддерживает operator % из QStringBuilder (или перегрузку + с дефайном). Но у обоих (QByteArray и QString) обязательный CoW, что может быть как минусом так и плюсом

В любом случае, expression template позволяет сделать такую штуку с любым строковым типом

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

Переменное число параметров функции в си поддерживалось с самого начала.

Сишный варарг не типобезопасен, что легко приводит к кровь-кишки-рап-дорасило при несовпадении типов аргументов с ожидаемыми

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

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

Придется развить воображение. Для примера, в Linux повсеместно применяются контейнеры, «виртуальные» функции и наследование. А goto вместо деструкторов это высший пилотаж.

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

переполнение signed int - максимальное значение знаковой i меньше максимального значения беззнакового size

Где ты там увидел тип size?

azelipupenko
()

Вот «Hello, world!» на C++/Qt:

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[]){
    QApplication app(argc, argv);

    QPushButton hello("Hello, world!");
    hello.resize(100, 30);

    hello.show();
    return app.exec();
}
Deathstalker ★★★★★
()
Ответ на: комментарий от azelipupenko

то есть, вы хотите сказать, что size у вас знаковый? это уже лет двадцать как моветон (ранее такое ещё допускалось в силу малых доступных объёмов ОЗУ)

ибо со знаковых рамеров на типичной машине вы огребёте на первом же файле весом более 2ГБ, а если речь не про ПК, то карма настигнет ещё раньше

да и откуда взяться знаковому size, если вся стандартная libc на size_t?

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

Тут никаких накладных расходов, скорее всего, не будет.

А вот и будет. И этот момент многие тупорылые плюсисты не понимают.

vector, а ровно и string, хранят данные в одном блоке памяти, а всю информацию - в другом.

Таким образом, получаем:

[size][pdata][other_shit]
        |
        V
        [......elements...]

Надо объяснять чем это чревато? Indirect адресацией, а следовательно, промахами кеша, нелокальностью памяти, тормозами, и прочим.

В нормальных же языках, а не в кривых плюсах, делается вот так:

[type_tag][size][...elements...]

И ссылка на объект указывает вот именно на оное, и иногда прямо на элементы, чтобы с помощью хаков модели адресации x86 того же, стирать метку типа и не иметь вообще никаких накладных расходов при обращении к массиву.

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

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

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

это уже лет двадцать как моветон
ибо со знаковых рамеров на типичной машине вы огребёте на первом же файле весом более 2ГБ

Спасибо, дорогой эксперт, за вашу куллстори. Теперь то я в курсе. Кулстори про моветоны и гиганские файлы - штука занятная, конечно, , но где вы увидели UB в том сниппете - остаётся загадкой. Ответ прост - там нет UB. Его придумал дорогой эксперт по куллстори. Лол :-)

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

А вот и будет. И этот момент многие тупорылые плюсисты не понимают.

Плюсисты, конечно, разные бывают.

vector, а ровно и string,

Да, да. Только причём тут std::array?

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

vector, а ровно и string, хранят данные в одном блоке памяти, а всю информацию - в другом.

Лол, что? в стандарте С++ не оговорено, как хранить данные. Тот же gcc (ЕМНИП) хранит информацию в том же блоке памяти, что и сами данные, во всяком случае, для string.

И да, нелокальность данных ещё не означает промах кеша.

например, в

for(size_t i = 0; i < vec.size(); i++){...}

при любой логически возможной имплементации вектора промах возможен только на первой итерации - для остальных значения size() уже будут закешированы

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

промахами кеша

Одним лишним промахом.

Ага, который возникает постоянно при работе с вектором.

Еще раз: по сравнению с «нормальными языками» добавляется 1 (один) лишний промах кэша. Который, внезапно, амортизируется до нуля просто при проходе поболее-менее большому вектору. Это не говоря о том, что при проходе делается какая-то полезная работа, которая вызывает свои промахи.

Добавим сюда еще смартпойнтеры, типа shared_ptr, с такими же проблемами

Ну, если «такими же», то глубоко пофиг.

и получается полный обосрамс и тормозилово

Выше один лиспер уже вычислял «раздутие кода от шаблонов». Намерял аж 0.1%. Но у него хоть цифры были, а у тебя только дым.

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

Надо объяснять чем это чревато? Indirect адресацией, а следовательно, промахами кеша, нелокальностью памяти, тормозами, и прочим.

Вот, кстати, объясни. Желательно, с примерами. А то в jemalloc, например, метаданные специально хранят отдельно от блоков данных, чтобы не засорять кеш. Это вопрос мутный, на словах не решается. Тесты нужны.

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

1) Если тип size - беззнаковый и sizeof(i)<=sizeof(size), вы получаете UB, по схеме, описанной выше

2) Если тип size - знаковый, вы получаете UB, так как все размеры в libc - в size_t. Никто сегодня на сях не хранит размеры в signed int по причине описанной выше. Есть 2 исключения: а) тяжёлое лагаси б)студентокод, написанный на основе устаревшего образовательного материала

3) Если тип sizeof(i) > sizeof(size) - у вас ошибка в коде + см. пункт 2

Так какой тип у этого вашего size?

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

shared_ptr используют неосиляторы unique_ptr, ну или для случаев «куяк-и в продакшен»

а у unique_ptr нет накладных расходов

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

Так какой тип у этого вашего size?

Во-первых. Всё просто. Там не указан тип. Поэтому все твои заявления про UB - это твои фантазии.

Во-вторых. Все вышеприведённые байки про sizeof, про размеры в libc, про хранение кем бы то ни было размеров в signed int не имеют отношения к UB в принципе.

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

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

shared_ptr используют неосиляторы unique_ptr

Глупости. shared_ptr используют те, у которых граф объектов сложнее дерева.

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

Наткнулся недавно на пару примеров «красоты» C++, вот этот мне особенно понравился:

#include <variant>
#include <iostream>

int main() {
    std::variant<std::string, bool> v = "Hello";
    auto x = std::get<0>(v) + ", World!";
    std::cout << x;
}

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