LINUX.ORG.RU

Контейнеры в C


2

3

Будучи сиплюсплюсником, меня давно интересует как те же задачи выполняются в C. Знаю, на ЛОРе есть множество приверженцев C, надеюсь они ответят на пару простых вопросов.

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

Не будем зарываться в дебри boost'а, возьмём простую задачу - контейнеры.

Для примера я взял односвязные списки в GTK GSList и Qt QList. QList позволяет хранить как простые, так и сложные типы с конструкторами, деструкторами, типы с общими данными. При этом накладных расходов на выделение в куче не происходит, а при реаллокации выбирается нужный алгоритм в зависимости от QTypeInfo<T>, к примеру для int будет вызван memcpy(), а для QString оператор копирования. Кроме того блок данных заранее резервируется и для сложных типов вызывается placement constructor. Для удаления данных по указателям используется алгоритм qDeleteAll(from,to), который сам дёрнет нужные конструкторы. Беглый просмотр GSList показал, что в нём можно хранить только указатели, со всеми вытекающими накладными расходами на аллокацию/уничтожение памяти, ручное кастирование, слежение за утечками, фрагментацию памяти.

Аналогичная ситуация со связными списками GList и QLinkedList.

Это даже не затрагивая вопрос о типизации, в C++ компилятор сразу даст по рукам при попытке записать в контейнер неверный тип или с помощью неявного преобразования с explicit-конструктором.

Далее, счётчики ссылок и деструкторы.

К примеру, в C++ список строк будет выглядеть как QList<QString>, при этом можно забыть про внутреннюю структуру строки - конструктор, деструктор и операторы копирования сами занимаются подсчётом ссылок, разделением и уничтожением данных. Вернуть строку из функции проще простого:

QString foo()
{
    return listOfStrings.at( 5 );
}

Этот код абсолютно безопасен и оптимален с точки зрения использования памяти и процессора, поскольку время тратится только на увеличение счётчика и копирование указателя.

В GTK я сходу нашёл GString:

struct GString 
{
  gchar *str;
  gint len;
};

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

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

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

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

могут, но посмотреть название ios-мода ничуть не дольше, чем FILE-мода

У fopen там модов-то, по пальцам пересчитать.

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

Так оно ж вроде архитектурнозависимо, если я не путаю=)

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

А все, я кажется понял, что ты имел в виду. Я о другом подумал.

Dudraug ★★★★★
()
Ответ на: комментарий от MuZHiK-2

Есть, конечно. В военной и авиапромышленности.

sv75 ★★★★★
()

«Для удаления данных по указателям используется алгоритм qDeleteAll(from,to), который сам дёрнет нужные конструкторы. Беглый просмотр GSList показал, что в нём можно хранить только указатели, со всеми вытекающими накладными расходами на аллокацию/уничтожение памяти, ручное кастирование, слежение за утечками, фрагментацию памяти.»

Я, конечно, дико извиняюсь, но что заставляет думать, что эти действия куда-то делись в случае с Qt? То, что их не нужно совершать разработчику, не означает, что их не нужно делать вообще. Процессор и его система команд одни и те же и какая разница что именно компилятор преобразует в двоичный код? Память нужно выделять и освобождать как ни крути. Даже если вы в Word'е объявление в подъезд набираете.

Собственно, это и послужило причиной появления и существования фреймворков (и даже ЯП) - вам дают блюдо какой-то степени готовности, по вкусу автора блюда, и смысл как раз в степени готовности блюда. Т.е. в том, на сокрытие чего и предоставление каких абстракций потратили свои ресурсы авторы/разработчики языка/фреймворка. Ну, за исключением чисто технических решений вроде «компиляторы vs интерпретаторы», разумеется. Стало быть, если вам надо минимум абстракций, но не хочется ассемблера, то можно взять C. Если вам хочется каких-то абстракций, но лень/некогда/дорого писать их руками, то можно воспользоваться С++. В C просто нет тех абстракций, поддержка которых заложена в компилятор C++, поэтому обозначенное ТС по-моему стоит рассматривать как корявую попытку сравнить фреймворки, один из которых использует менее абстрагированный ЯП. Я думаю, что правильнее было бы сравнивать GTK с реализацией поддержки абстракций C++ в g++. А так получается, что сравниваются жизнь на еде из ресторана и жизнь с приготовлением еды на своей кухне.

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

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

чистый си предоставляет полную свободу в конструировании этих самых абстракций

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

Для кого-то это новость?..

А речь не об этом совсем.

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

хочется каких-то абстракций, но лень/некогда/дорого писать их руками

же.

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

чистый си предоставляет полную свободу в конструировании этих самых абстракций

Изначальный вопрос темы был как раз в том этом - да, мы можем ввести эти абстракции, но насколько эффективно (с точки зрения эффективности выполнения относительно времени/памяти) они будут выполнятся? И можно ли их оптимизировать?

Ответ тоже уже был - ввести абстракции-то можно (расширить runtime), но компилятор-то мы дописать не сможем (в случае Си) - не получится привнести каких-нибудь оптимизаций, вроде шаблонных. А вот в C++ есть такие возможности по оптимизации кода - соответствующие абстракции в C++ просто «быстрее» работают.

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

> А вот в C++ есть такие возможности по оптимизации кода - соответствующие абстракции в C++ просто «быстрее» работают.

По-моему «быстрее» тут не совсем уместно. Например, шаблоны, imho, можно рассматривать больше как оптимизацию вот именно что текста программы, чем как ускоритель работы самой программы. Да, за счёт уменьшения количества набираемого текста несколько сокращается время разработки, но это уже плюсы тем, кто зарабатывает разработкой ПО и у кого время - деньги. Производительность ПО тут скорее деградирует или как минимум не повышается. Ну и опять же компилятор усложняется и дольше компилирует.

Любая абстракция стоит каких-то ресурсов, вне зависимости от ЯП и фреймворка, так как её нужно как-то поддерживать, чем-то обеспечивать. Инструкции процессора - элементарные операции - одни и те же что с абстракциями, что без. Поэтому для представления какой-то абстракции (как дополнительного функционала) инструкций потребуется больше. С этой точки зрения использование «абстрактного» ЯП или фреймворка является перекладыванием расходов с производителя на потребителя - производитель сократит затраты на разработку за счёт использования ресурсоёмких абстракций, а вот потребителю для сохранения скорости работы потребуется придётся приобретать более мощное железо, которые будет обрабатывать увеличившееся из-за абстракций количество кода быстрее. Хотя функциональность ПО нередко остаётся той же - что 20 лет назад тексты набирали и распечатывали, что сейчас набираем и распечатываем. Только вот современные текстовые редакторы на железе 20-летный давности скорее всего не задышат.

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

> Производительность ПО тут скорее деградирует или как минимум не повышается

в топике уже рассматривались примеры кода - производительность кода на С оказалась ниже( может это говорит только о данных примерах, но других никто не предоставил )

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

и это при том, что по-честному надо брать вариант с g_strdup и добавить удаление каждой строки:

g_list_foreach (list, (GFunc) g_free, NULL);

которое там забыли, т.к. иметь указатель на одну строку нет смысла

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

По ссылке представлен блок на «чистом C++», вот такой:

#include <string>  
#include <list>  
#include <stdlib.h> 
  
struct person   
{   
    std::string nick;   
    int id;   
};   
   
   
int main(int argc, char *argv[])   
{   
    std::list<person> list; 
    int count = atoi(argv[2]);     
    list.resize(count);  
      
    const std::string str = argv[1];   
 
    std::list<person>::iterator it = list.begin();  
    for( int i = 0 ; i < count ; ++i, ++it ) {  
       it->nick = str;  
       it->id   = i;  
    }  
} 
В моей системе это работает несколько медленнее, чем у автора по ссылке:
> time ./cpp_list dendy 10000000

real    0m1.930s
user    0m1.660s
sys     0m0.252s

> time ./cpp_list dendy 10000000

real    0m1.891s
user    0m1.620s
sys     0m0.268s

> time ./cpp_list dendy 10000000

real    0m1.863s
user    0m1.648s
sys     0m0.208s

> time ./cpp_list dendy 10000000

real    0m1.872s
user    0m1.692s
sys     0m0.176s

> time ./cpp_list dendy 10000000

real    0m1.861s
user    0m1.600s
sys     0m0.256s

Выполняющий то же самое код на «чистом C» у меня получился такой:

#include <stdlib.h> 
#include <string.h> 

struct person {
    char *nick;
    int id;
};

int main(int argc, char *argv[]) {
    struct person *p;

    int structSize = sizeof(struct person);
    int i = 0;
    int nameLen = strlen(argv[1]);
    int count = atoi(argv[2]);
    struct person **spArray = malloc(count * structSize);
    while (i < count) {
        p = malloc(structSize);
        p->nick = calloc(1, nameLen + 1);
        memcpy(p->nick, argv[1], nameLen);
        p->id = i;
        spArray[i] = p;
        i++;
    }
    /*for (i = 0; i < count; i++) {
        free(spArray[i]->nick);
        free(spArray[i]);
    }
    free(spArray);*/
}
Без очистки памяти выполняется так:
> time ./c_list dendy 10000000

real    0m1.025s
user    0m0.672s
sys     0m0.356s

> time ./c_list dendy 10000000

real    0m1.014s
user    0m0.656s
sys     0m0.356s

> time ./c_list dendy 10000000

real    0m1.013s
user    0m0.612s
sys     0m0.400s

> time ./c_list dendy 10000000

real    0m1.052s
user    0m0.624s
sys     0m0.420s

> time ./c_list dendy 10000000

real    0m1.031s
user    0m0.640s
sys     0m0.392s
С задействованным кодом очистки:
> time ./c_list dendy 10000000

real    0m1.363s
user    0m1.004s
sys     0m0.352s

> time ./c_list dendy 10000000

real    0m1.373s
user    0m1.004s
sys     0m0.368s

> time ./c_list dendy 10000000

real    0m1.351s
user    0m0.980s
sys     0m0.364s

> time ./c_list dendy 10000000

real    0m1.344s
user    0m0.960s
sys     0m0.380s

> time ./c_list dendy 10000000

real    0m1.377s
user    0m1.052s
sys     0m0.312s

Судя по sys, программа на C больше времени проводит в ядре, т.е. userspace кода в ней меньше и затрачиваемое на операции с памятью время в общем времени заметнее. Для C++ userspace кода похоже больше (шаблоны и итераторы?), а вот операций выделения памяти похоже меньше, стало быть, мой код на C можно ещё пооптимизировать в эту сторону для уменьшения количества «дорогих» системных вызовов. :)

Ну и это, размеры:

> ls -l
-rwxr-xr-x 1 user group  9708 Авг 11 12:39 c_list
-rwxr-xr-x 1 user group 22152 Авг 11 12:35 cpp_list

anonymous
()

Да к сожалению для C нет подобных библиотек как в C++ для работы с контейнерами, обычно, в различных проектах это решается прикручиванием своих велосипедов различной степени качества. К слову сказать в C++ тоже всё не так безоблачно как кажется несмотря на существование библиотеки STL реализаций которой тоже несколько, в более менее больших проектах всегда почему то присутствуют свои шаблоны, для реализации контейнеров, причем иногда как скажем в wxWidgets контейнеры реализованы на C++ с использованием макросов а не шаблонов. Если вас интересуют например «матерые» хеш таблицы на C можно посмотреть на http://www.sunrisetel.net/software/devtools/sunrise-data-dictionary.shtml GTK не самый удачный пример хорошо реализованной библиотеки на C в некоторых местах особенно когда речь идет о контейнерах и структурах данных GTK скорей пример того как не нужно писать программы. Также как Qt сложно назвать образцовым примером библиотеки на C++

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

> причем иногда как скажем в wxWidgets контейнеры реализованы на C++ с использованием макросов а не шаблонов

очередной дибилизм wxWidgets, который вероятно остался с начала 90-х

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

Разве это что-то принципиально меняет? :) Специально для вас, на незацикленном двусвязном списке:

#include <stdlib.h> 
#include <string.h> 

struct person {
    struct person *first;
    struct person *next;
    struct person *prev;
    char *nick;
    int id;
};

int main(int argc, char *argv[]) {
    struct person *p, *first, *last, *prev;

    int structSize = sizeof(struct person);
    int i = 0;
    int nameLen = strlen(argv[1]);
    int count = atoi(argv[2]);

    while (i < count) {
        if (0 == i) {
            first = malloc(structSize);
            first->prev = NULL;
            first->nick = calloc(1, nameLen + 1);
            memcpy(first->nick, argv[1], nameLen);
            first->id = 0;
            prev = first;
        }
        else {
            p = malloc(structSize);
            p->first = first;
            if (i == (count - 1)) p->next = NULL;
            prev->next = p;
            p->prev = prev;
            p->nick = calloc(1, nameLen + 1);
            memcpy(p->nick, argv[1], nameLen);
            p->id = i;
            prev = p;
        }
        i++;
    }
    /*p = first; 
    do { 
        free(p->nick); 
        if (p != first) free(p->prev); 
        if (NULL == p->next) last = p; 
        p = p->next; 
    } while (NULL != p); 
    free(last);*/
}
Результат забега без освобождения памяти:
> time ./c_list dendy 10000000

real    0m1.074s
user    0m0.652s
sys     0m0.420s

> time ./c_list dendy 10000000

real    0m1.159s
user    0m0.716s
sys     0m0.408s

> time ./c_list dendy 10000000

real    0m1.077s
user    0m0.680s
sys     0m0.380s

> time ./c_list dendy 10000000

real    0m1.067s
user    0m0.696s
sys     0m0.348s

> time ./c_list dendy 10000000

real    0m1.061s
user    0m0.660s
sys     0m0.400s
С освобождением:
> time ./c_list dendy 10000000

real    0m1.534s
user    0m1.148s
sys     0m0.380s

> time ./c_list dendy 10000000

real    0m1.489s
user    0m1.036s
sys     0m0.440s

> time ./c_list dendy 10000000

real    0m1.432s
user    0m0.980s
sys     0m0.432s

> time ./c_list dendy 10000000

real    0m1.453s
user    0m1.072s
sys     0m0.364s

> time ./c_list dendy 10000000

real    0m1.441s
user    0m0.992s
sys     0m0.432s

Вывод: похоже освобождать память надо пореже, лучше сразу оторвать побольше и просто чистить время от времени. :) Любопытно, что во втором случае возросло время, проводимое в userspace, что наводит на мысль о существовании каких-то дополнительных и нехилых действий при освобождении памяти внутри, например, libc.

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

я не знаю как у вас, а у меня получилось:

g++ -O3 ./1.cpp
time ./a.out dendy 10000000

real 0m1.820s
user 0m1.575s
sys 0m0.243s

gcc -O3 ./1.c
time ./a.out dendy 10000000

real 0m2.859s
user 0m2.382s
sys 0m0.471s

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

gcc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~19/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

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

Хм, с -O{1,2,3} и у меня участники поменялись местами. До этого собирал без флагов вообще.

> gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-cld --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1)

Похоже на то, что оптимизация для C в gcc оставляет желать много лучшего и C-программы при помощи gcc лучше собирать без его оптимизаций. Ну или как минимум программы, подобные написванным выше. :)

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

Да самое главное то в том, что stl без минимальных оптимизаций пользоваться нет смысла - функции не инлайнятся, тормоза жуткие.

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

> тормоза жуткие.

как бы anonymous привел бенчмарки - «жуткие тормоза» stl без оптимизации по скорости мало чем отличаются от таковых в С

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

> от таковых в С ... при включённой оптимизации в gcc.

Если собирать без оптимизации - код на C работает хорошо и только оптимизированный g++ код C++ сравним с ним по производительности. Т.е. тут мы упираемся в фокусы компилятора. Без каких-либо оптимизаций компилятора код на C работает до 55% (примерно 1с против примерно 1.8с в моей системе) быстрее кода на C++.

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

> работает до 55% (примерно 1с против примерно 1.8с в моей системе)

если сознательно «отключить» free? это абсолютно несерьезно

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

и да, С++-й вариант также без удаления( abort() после всех действий ):

real 0m1.000s
user 0m0.673s
sys 0m0.206s

точно также можно взять PooledList - и это будет и честный и быстрый вариант

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

«до 55%». Оно и с free() заметно быстрее - примерно 1.5 против примерно 1.8 (на списках, на массиве отрыв ещё больше). Т.е. тут возможны варианты, смотря по фантазии.

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

> на массиве отрыв ещё больше

вы упорно сравниваете разные вещи :) массив надо сравнивать с vector, а никак не с list

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

С abort() перед последней закрывающей скобкой и со сборкой без оптимизации C++ код у меня работает так:

> time ./cpp_list dendy 10000000
Аварийный останов

real    0m1.520s
user    0m1.328s
sys     0m0.168s

Несколько быстрее конечно, но до C-кода тоже без освобождения памяти и со списком всё равно ещё примерно полсекунды. :)

вы упорно сравниваете разные вещи

Я не сравниваю, это просто информация о том, что любая комбинация для C-кода из приведённых оказывается быстрее кода на C++. Близко код на C++ подбирается с сишному только в случае с abort() для C++ и free() + список для C, что логично (в коде C++ выполняется меньше действий, в коде C - больше), но, как вы верно заметили, это разные вещи. :)

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

Близко код на C++ подбирается с сишному только в случае с abort() для C++ и free() +

список для C

у нас с вами какие-то разные резальтаты получаются ;) только что проверил:

C++ с удалением:

$ g++ ./1.cpp $ time ./a.out dendy 10000000

real 0m2.596s user 0m2.339s sys 0m0.252s

С также с удалением:

$ gcc ./1.c $ time ./a.out dendy 10000000

real 0m3.013s user 0m2.501s sys 0m0.508s

код на С++ пришлось подрихтовать - т.к. без оптимизации g++ крешился на компиляции( о_О )

#include <string>   
#include <list>   
#include <stdlib.h>  
   
struct person    
{    
    int id;    
    std::string nick;    
};    
    
static person it;
    
int main(int argc, char *argv[])    
{    
    std::list<person> list;  
    int count = atoi(argv[2]);      
       
    const std::string str = argv[1];    
  
    for( int i = 0 ; i < count ; ++i ) {   
       it.nick = str;   
       it.id   = i;
       list.push_back( it );
    }   
}  
ahonimous
()
Ответ на: комментарий от ahonimous

> без оптимизации g++ крешился на компиляции

У меня как раз нормально собирался. Похоже все эти замеры - средняя т-ра по больнице. :) Компиляторы разных версий вносят неизвестную погрешность.

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

> Похоже все эти замеры - средняя т-ра по больнице. :)

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

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

Я только увидел, что оптимизированный по g++ код C++ быстрее неоптимизированного кода C++ и сравним по скорости с неоптимизированным C-кодом. Хотелось бы ещё сравнить с оптимизированным gcc C-кодом, но существенное в результате оптимизации ухудшение производительности для меня выглядит нонсенсом, поэтому для меня тут пока сравнивать нечего.

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

>> А вот в C++ есть такие возможности по оптимизации кода - соответствующие абстракции в C++ просто «быстрее» работают.

не верю в то, что в плюсах это есть, а в си нет

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

Еще версия компилятора:

> gcc -v
Спецификации прочитаны из /usr/lib/gcc/i486-slackware-linux/4.3.3/specs
Целевая архитектура: i486-slackware-linux
Параметры конфигурации: ../gcc-4.3.3/configure --prefix=/usr --libdir=/usr/lib --enable-shared --enable-bootstrap --enable-languages=ada,c,c++,fortran,java,objc --enable-threads=posix --enable-checking=release --with-system-zlib --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --with-gnu-ld --verbose --with-arch=i486 --target=i486-slackware-linux --build=i486-slackware-linux --host=i486-slackware-linux
Модель многопоточности: posix
gcc версия 4.3.3 (GCC)
Сборка без оптимизации для обоих языков:
> time ./c_list dendy 10000000

real    0m4.703s
user    0m3.211s
sys     0m0.686s

> time ./cpp_list dendy 10000000

real    0m3.627s
user    0m3.227s
sys     0m0.401s
Сборка с "-O3" для обоих языков:
> time ./c_list dendy 10000000

real    0m2.994s
user    0m2.217s
sys     0m0.677s

> time ./cpp_list dendy 10000000

real    0m2.300s
user    0m1.559s
sys     0m0.464s

В обеих программах очистка памяти включена.

imho, бред, все эти замеры лишены смысла - компилятор не даёт надёжного результата.

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

> imho, бред, все эти замеры лишены смысла - компилятор не даёт надёжного результата.

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

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

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

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

> Повторюсь - разные версии компиляторов дают разные результаты

и я повторюсь - «C++ всегда быстрее с включенной оптимизацией» :)

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

«C++ всегда быстрее с включенной оптимизацией» == «Смазанный вакуумный сферический конь всегда быстрее»

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

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

> Но, размуеется, вы вправе думать любую ахинею, у нас вроде как свободная страна. :)

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

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

C++ оказался быстрее потому что он «читирит» чит заключается в том что используются стринги из стд с референс коунтингом подставляем тот же чит в код на C first->nick=str (без выделения памяти) и всё встанет на свои места C код будет в разы быстрее

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

>C++ оказался быстрее потому что он «читирит»

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

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

> подставляем тот же чит в код на C first->nick=str (без выделения памяти) и всё встанет на свои места

нет - не встает, если заменить С++-е строки на сишные в С++-м примере, то у меня он все-равно быстрее

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

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

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