LINUX.ORG.RU

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

 ,


7

9

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

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

Извиняюсь, в Rust коде используется split_whitespace(), поэтому это reverse1 работает не так как надо, разделяя слова только по пробелам, а не по всем пробельным символам, reverse2 работает правильно.

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

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

Ну оно то так, но есть еще понятие «constant expression». Т.е. то, что означено constexpr знгачит что *может* быть использовано в, собственно, «constant expression».

Т.е. если имеем constant expression

3 + 2;
то почему вот такое уже может не быть constant expression?
constexpr add(int a, int b) { return a + b; }
3 + add(1, 1);

С другой стороны да, должен признать что не нашел формального требования constexpr implies constant expression. Но тогда бы оно значило, что constexpr не можно использовать в рантайме?

А в стандарте много чего написано про constexpr, лень вычитывать :-/

В общем случае, если в сабжевом примере принудительно ввести constant-expression контекст, то ASM не изменится, а уверенность в compile-time вычислении уже будет:

    // если result не можно вычислить на єтапе компиляции -- не скомпилируется
    constexpr auto result = Rational(1,2)+Rational(1,3)+Rational(1,4)+Rational(1,5); 
    return result.denominator;

OK: https://wandbox.org/permlink/3Zd894d5VoyuCmJD
FAIL: https://wandbox.org/permlink/PcuzNW5KePWkvKdc

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

Фу, как можно метапрограммирование считать чем-то красивым? Вопрос риторический. Имхо, на си все это гораздо красивее.

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

Имхо, на си все это гораздо красивее.

Метапрограммирование на C красивее? Можно на примерах показать?

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

Интроспекция, нормальное функциональное программирование, one way to do it, сборщик мусора или система отслеживания владения, отсутствие трындеца в культуре разработки и стандартной библиотеке, отсутствие кодогенерации на каждый чих, отсутствие необходимости осваивать слоеный пирог независимых неродственных языков...

Не пойми меня неправильно, идеального языка нет, но C++ — совсем ногострел, который кроме как для поддержки legacy и отрицательного примера языкостроителям и не годен никуда.

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

Интроспекция, нормальное функциональное программирование, one way to do it, сборщик мусора или система отслеживания владения, отсутствие трындеца в культуре разработки и стандартной библиотеке, отсутствие кодогенерации на каждый чих, отсутствие необходимости осваивать слоеный пирог независимых неродственных языков...

Из всего перечисленного объективным можно назвать только отсутствие интроспекции.

Все остальное или неосиляторство или непонимание сути вещей.

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

Все остальное — джентльменский набор языка общего назначения 21 века и тыканье в C++-специфичный отстой.

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

Для тех, кому нужен GC, еще с прошлого века существует куча языков с GC. А C++ нужен именно такой какой он есть — без GC. И без проистекающих из GC плюшек, вроде полноценной поддержки ФП.

Если вы этого в 21-ом веке не понимаете, значит пытаетесь применять C++ там, где ему не место. И это вовсе не проблема C++.

eao197 ★★★★★
()

RAII лямблы и статический duck typing позволяют делать элегантный код.

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

Фу, как можно метапрограммирование считать чем-то красивым?

Лично я получил истинное насаждение после реализации своего первого списка типов.

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

http://en.cppreference.com/w/cpp/language/constant_expression#Core_constant_e...

Пункт 6 интересен: «Whether standard library undefined behavior is detected is unspecified.»

То есть допустимо, что в компиляторе в процессе компиляции может возникнуть UB, вызванный исполнением constexpr функции?

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

Ты неправильно прочитал. Не было у него того якобы заявления, которое ты пытаешься оспорить. По сути, ты споришь с собой.

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

Нить разговора началась с:

Если же говорить о красивых архитектурных решениях, то мне нравится stl. Попробуй написать что-либо на голых сях, а потом на С++11/14/17 с применением STL, контраст тебя поразит.

потом продолжилась:

Я имел в виду красоту самой идеи STL, корни которой уходят в метапрограммирование. В Си такого нет.

на что было заявлено:

Имхо, на си все это гораздо красивее.

Вот пускай на примерах и покажет, насколько «все это» красивее на си. Чтобы под «всем этим» не понималось.

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

Постеснялись бы хоть, нас могут читать дети.

А при чем тут дети? Ничего пошлого не имелось в виду. Впрочем, у каждого свои ассоциации с понятием наслаждения - я не осуждаю ;)

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

на что было заявлено

Имхо, на си все это гораздо красивее.

Там в сообщении было три предложения. Первые два ты пропустил намеренно? Или просто не считаешь, что они влияют на смысл третьего, и его можно вытащить и просто прицепить к контексту предыдущего сообщения? Если да, то это всё равно что выбрасывать «не» из «не хочу».

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

Там в сообщении было три предложения. Первые два ты пропустил намеренно? Или просто не считаешь, что они влияют на смысл третьего

Я (тоже) считаю, что на смысл третьего они не влияют. Риторический вопрос вообще на смысл не влияет.

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

Если driver говорит, что он ценит в STL идею, корни которой идут из метапрограммирования, а rj45 вопрос о красоте метапрограммирования объявляет риторическим, но после заявляет о «Имхо, на си все это гораздо красивее.», то я не могу исключить из «все это» то самое метапрограммирование.

Но, даже если речь не про метапрограммирование, пусть rj45 покажет хоть что-нибудь, что он в Си считает гораздо более красивым, чем в C++.

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

s3 = s1 + " " + s2;

Прям как в нормальных языках, лол. Еще бы все остальное было как в нормальных языках

Только не забываем, что в этих ваших «нормальных» языках, включая кресты, когда там используются подобные «нормальные» конструкции, при выполнении данной операции сначала создаётся новая временная строка, содержащая s1 и " ", затем эта строка объединяется с s2 в ещё одну временную строку, после чего всё это копируется в s3, а временные строки удаляются. Итого мы имеем 2 лишних выделения и высвобождения памяти и 2 лишних копирования строк. А на «ненормальном» си нет ничего лишнего (если заранее выделили достаточный буфер для s3):

strcpy(s3, s1);
strcat(s3, " ");
strcat(s3, s2);

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

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

на С этот код превратится либо в тормознутое говно либо в проект размером в линукс кернел

На си так просто никто не будет делать. А сделают то же самое нормальными си-средствами, и всё будет намного быстрее и не намного длиньше.

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

А вот и знатоки CSS подтянулись.

сначала создаётся новая временная строка, содержащая s1 и " ", затем эта строка объединяется с s2 в ещё одну временную строку, после чего всё это копируется в s3, а временные строки удаляются.

s3 = s1;
s3 += " ";
s3 += s2;

Это если ты не хочешь пользоваться ostream.

если заранее выделили достаточный буфер для s3

strcpy

strcat

strcat

facepalm.jpg

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

при выполнении данной операции сначала создаётся новая временная строка, содержащая s1 и " ", затем эта строка объединяется с s2 в ещё одну временную строку, после чего всё это копируется в s3, а временные строки удаляются.

Так ли это для C++11 и более современных стандартов, в которых есть rvalue references и move semantic?

eao197 ★★★★★
()
Ответ на: комментарий от tailgunner
s3 = s1;
s3 += " ";
s3 += s2;

Это если ты не хочешь пользоваться ostream.

Я написал:

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

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

А так да, на си++ ещё и strcpy со strcat можно, которые он унаследовал из си. Но си стимулирует писать эффективно, а си++ стимулирует писать «нормально». Про «нормальные» языки я уже и не говорю, т. к. там как правило можно написать только нормально (т. е. неэффективно).

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

при выполнении данной операции сначала создаётся новая временная строка, содержащая s1 и " ", затем эта строка объединяется с s2 в ещё одну временную строку, после чего всё это копируется в s3, а временные строки удаляются.

Так ли это для C++11 и более современных стандартов, в которых есть rvalue references и move semantic?

Т. к. строки s1 и s2 компилятор и библиотека в данном случае разрушать не имеют права, то в лучшем случае мы избавимся от 1 лишнего временного объекта, но 1 всё равно останется.

aureliano15 ★★
()

Посмотри реализацию любого контейнера, не прибитого гвоздями к одному типу, на C и C++. В сишке будет трэш и угар из макросов или void*, а в C++ - типобезопасный шаблонный код

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

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

Пфф, перегружается operator+ с использованием билдера, в результате буфер нужного размера выделяется сразу, и никаких лишних копирований. В Qt есть из коробки

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

Но си стимулирует писать эффективно, а си++ стимулирует писать «нормально».

Твой код с strcpy и strcat - это потенциальная дыра. А если писать этот код надежно, то он сведется либо к 1) коду, который усекает данные, либо к 2) в общем, эквиваленту кода на Си++98, который к тому же не поддается оптимизации за счет тех самых rvalue references и move semantics. И, конечно, во втором случае это отнюдь не простые и понятные strcpy strcat strcat.

Про «нормальные» языки я уже и не говорю, т. к. там как правило можно написать только нормально (т. е. неэффективно).

Насколько я знаю, в Java конструкция s1 + " " + s2 преобразуется в вызовы StringBuilder, так что нет, и здесь ты неправ.

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

заранее выделили достаточный буфер для s3

Если уж набрасывать демонстрировать красоту сишечки, то лучше так:

#include <stdio.h>
#include <stdlib.h>

int
main()
{
	FILE *stream;
	size_t len;
	char *str;

	stream = open_memstream(&str, &len);
	fprintf(stream, "%s %s", "The", "string");
	fclose(stream);

	puts(str);
	free(str);

	return 0;
}
Deleted
()
Ответ на: комментарий от annulen

В сишке будет трэш и угар из макросов или void*, а в C++ - типобезопасный шаблонный код

С этим-то я как раз не спорю.

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

Про «нормальные» языки я уже и не говорю, т.к. там как правило можно написать только нормально (т. е. неэффективно).

Вот тут, например, будет всего один вызов malloc правильного размера, и никаких лишних копирований. Разве выглядит «ненормально»?

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

Пфф, перегружается operator+ с использованием билдера, в результате буфер нужного размера выделяется сразу, и никаких лишних копирований. В Qt есть из коробки

А как в выражении, включающем 2 сложения строк, заранее узнать размер нужного буфера, чтоб гарантированно выделить его сразу 1 раз?

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

Твой код с strcpy и strcat - это потенциальная дыра. А если писать этот код надежно, то он сведется либо к 1) коду, который усекает данные, либо к 2) в общем, эквиваленту кода на Си++98, который к тому же не поддается оптимизации за счет тех самых rvalue references и move semantics.

Почему? Мне достаточно заранее выяснить сумму длин строк s1 и s2, прибавть к ним 2 (" " + «\0») и выделить память. И никакой дыры. Разумеется, если я забуду проверить длины, то дыра появится.

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

Про «нормальные» языки я уже и не говорю, т. к. там как правило можно написать только нормально (т. е. неэффективно).

Насколько я знаю, в Java конструкция s1 + " " + s2 преобразуется в вызовы StringBuilder, так что нет, и здесь ты неправ.

С этим спорить не буду, т. к. не знаю.

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

Если уж набрасывать демонстрировать красоту сишечки, то лучше так

Согласен.

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

Вот тут, например, будет всего один вызов malloc правильного размера, и никаких лишних копирований. Разве выглядит «ненормально»?

Это пример из несколько другой области. Я сравнивал запись вида str0 = str1 + str2 + str3 с записью str0=str1; str0+=str2; str0+=str3;

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

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

http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/tools/qstringbuilder.h

https://trac.webkit.org/browser/webkit/trunk/Source/WTF/wtf/text/StringOperat...

Ну естественно, qt работает на крестах, кто ж спорит? И браузеры проще писать на крестах. А для некоторых задач удобнее bash. Это значит кресты курят в сравнении с башем? А вот ядро лучше писать на си. Можно, конечно, и на крестах, но либо крестовые фичи использоваться не будут, а значит это будет тот же си, либо получится уг.

Там, где такие «копейки», как лишнее выделение буфера, не важны, си тоже не нужен. Но вот там, где это важно, си незаменим.

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

А вот ядро лучше писать на си.

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

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

Эт почему еще «крестовые фичи использоваться не будут»? С библиотекой придется поужаться (, исключения тоже могут не прокатить (хотя смотря как это ядро реализовано), а все остальное не имеет приниципиальных проблем

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

Красивый код на крестах — это тот код, в котором крестов мало.

Doom 3 что ли? Это там, где строили велосипед чуть ли не половину STL реализовали?

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

Тебе привели пример как в С++ делается то же самое, только с приятным синтаксисом (+), а ты шлангуешь

Знаем, знаем. Божественный Qt. Вот только, чем больше проектов используют Qt, тем больше утверждений от C#/Java программистов, зачем нам ваш С/С++ у нас и C#/Java почти не отстают от ваших быстрых языков :)

Мини тест:

#define NONIUS_RUNNER
#include <nonius/nonius.h++>
#include <nonius/main.h++>

#include <string>
#include <cstring>
#include <QtCore>


NONIUS_BENCHMARK ("c", [] (nonius::chronometer meter)
{
    const char* s1 = "hello";
    const char* s2 = "world";
    thread_local static char s3[256]={0};
    meter.measure ([&] (const size_t /*run*/)
    {
        strcpy(s3, s1);
        strcat(s3, " ");
        strcat(s3, s2);
        return s3;
    });
})

NONIUS_BENCHMARK ("c++", [] (nonius::chronometer meter)
{
    const std::string s1 = "hello";
    const std::string s2 = "world";
    meter.measure ([&] (const size_t /*run*/)
    {
        std::string s3;
        s3.reserve(s1.size() + 1 + s2.size());
        s3 += s1;
        s3 += " ";
        s3 += s2;
        return s3;
    });
})


NONIUS_BENCHMARK ("Qt", [] (nonius::chronometer meter)
{
    const QString s1 = "hello";
    const QString s2 = "world";
    meter.measure ([&] (const size_t /*run*/)
    {
        QString s3 = s1 + " " + s2;
        return s3;
    });
})
clock resolution: mean is 44.3771 ns (10240002 iterations)

benchmarking c
collecting 100 samples, 6558 iterations each, in estimated 3.9348 ms
mean: 6.75393 ns, lb 6.72732 ns, ub 6.8659 ns, ci 0.95
std dev: 0.240033 ns, lb 0.0392782 ns, ub 0.56316 ns, ci 0.95
found 9 outliers among 100 samples (9%)
variance is moderately inflated by outliers

benchmarking c++
collecting 100 samples, 1877 iterations each, in estimated 4.3171 ms
mean: 22.6757 ns, lb 22.6529 ns, ub 22.7331 ns, ci 0.95
std dev: 0.161126 ns, lb 0.00766571 ns, ub 0.297814 ns, ci 0.95
found 7 outliers among 100 samples (7%)
variance is unaffected by outliers

benchmarking Qt
collecting 100 samples, 122 iterations each, in estimated 4.453 ms
mean: 339.169 ns, lb 337.292 ns, ub 342.762 ns, ci 0.95
std dev: 12.7975 ns, lb 7.63821 ns, ub 19.3936 ns, ci 0.95
found 13 outliers among 100 samples (13%)
variance is moderately inflated by outliers

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

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

Языкам общего назначения никогда не заменить сишечку, согласен. Только вот C++ тоже никогда не заменить сишечку, да и ее ниша с каждым годом все уже. Числодробилки и прикладуха уже почти все, а в системном программировании и эмбедщине плюсы и даром не сдались. Даже как язык написания интерпретатором и target language для других высокоуровневых языков он не прижился.

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