Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Отличия в оптимизации C и C++

#cpp #c


Какой код компилируется Си и С++, корректно работает, но при этом может отличается
по быстродействию вследствие различий стандартов C и C++?

Пример: malloc(sizeof('x') * 100500) выделит в sizeof(int) раз больше памяти в Си,
что теоретически может замедлить программу.
    


Ответы

Ответ 1



Если абстрагироваться от вопросов качества реализации компиляторов С vs. С++, то отличаться по быстродействию "один и тот же код" в С и С++ может только в том случае, если он отличается по семантике. То есть "одним и тем же кодом" в такой ситуации он будет только с чисто косметически-визуальной точки зрения. Можно грубо выехать на различиях в правилах name lookup struct S { int a[10]; }; int main() { struct Local { struct S { int a[10000]; } s; }; struct S s = { 0 }; // `sizeof s`??? } В языке С здесь объявляется и обнуляется "большой" объект, а в С++ - "маленький". Но это уж слишком грубо. Свойство языка С++ бережно сохранять lvalue-ность результатов выражений приведет к тому, что цикл for (unsigned n = sizeof (1 ? "Hello" : "World"); n > 0; --n) ; будет выполняться разное количество раз в С и в С++. Это тоже довольно грубый прием. Далее стоит упомянуть следующее const int N = 10; int A[N][N][N]; В языке С++ это - обычный массив, а в языке С - это Variable Length Array с потенциальными накладными расходами во время выполнения. Продолжая тему VLA, операнд вот такого sizeof в языке С является вычислимым выражением (подразумевая вышеприведенное объявление A) unsigned n = sizeof A[rand() % N][rand() % N]; И хотя, согласно спецификации языка С, вычисления выражений-индексов в данном случае не требуется (ибо результат от них не зависит), компилятор имеет право их вычислить (GCC, что интересно, вычисляет). В C++ же операнд sizeof вычислимым не является никогда, т.е. такой sizeof вычисляется во время компиляции и выполнимого кода не порождает. Ворох мелочей может скрываться в различиях правил sequencing этих языков. То же свойство сохранения lvalue-ности результатов выражений в С++ приводит к тому, что его правила sequencing более строги и ограничивающи, чем аналогичные правила в С. Это теоретически может привести к более эффективному коду в С. (Но придумать пример, где бы это давало осязаемый эффект навскидку непросто.) Потенциальная необходимость обработки исключений в С++ и раскрутки стека - еще одна причина, по которой практически любой идентичный С и С++ код может быть странслирован менее эффективно в С++.

Ответ 2



Теоретически fabs((char)x) и собратья из cmath, имеющие перегрузки для целочисленных типов, могут работать быстрее. Появились в С++11, если не ошибаюсь.

Комментариев нет:

Отправить комментарий