Абстракция с нулевой стоимостью — это метод программирования на C++, направленный на устранение накладных расходов, связанных с использованием абстракций. Это достигается за счет использования оптимизации времени компиляции для устранения дополнительных накладных расходов, возникающих во время выполнения.

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

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

Для достижения абстракции с нулевой стоимостью C++ использует несколько механизмов:

  1. Полиморфизм времени компиляции: шаблоны C++ предоставляют механизм универсального программирования, позволяющий генерировать код во время компиляции для различных типов и конфигураций. Шаблоны позволяют создавать многоразовый и эффективный код без накладных расходов во время выполнения.
  2. Встраивание: компиляторы C++ могут встраивать вызовы функций, что означает, что код функции вставляется непосредственно в место вызова. Встраивание устраняет накладные расходы на вызовы функций и обеспечивает лучшие возможности оптимизации, позволяя компилятору видеть полный контекст кода.
  3. Статическая диспетчеризация: C++ поддерживает статическое связывание, также известное как раннее связывание или связывание во время компиляции, когда соответствующая реализация функции определяется во время компиляции на основе статического типа объекта. Это позволяет компилятору генерировать эффективный код без необходимости динамической диспетчеризации или вызовов виртуальных функций.
  4. Интеллектуальная оптимизация. Современные компиляторы C++ используют различные методы оптимизации для устранения избыточных операций, сокращения доступа к памяти и оптимизации кода на основе целевой архитектуры. Эти оптимизации помогают минимизировать влияние абстракции на производительность.

Комбинируя эти механизмы, C++ стремится предоставить высокоуровневые абстракции, которые можно использовать для написания выразительного и удобочитаемого кода, сохраняя при этом производительность на уровне низкоуровневого кода. Однако важно отметить, что абстракция с нулевой стоимостью является скорее руководящим принципом, чем абсолютной гарантией. В некоторых случаях способ использования или составления абстракций может привести к снижению производительности, поэтому для обеспечения эффективности кода необходимо тщательное рассмотрение.

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

template <typename T>
T sum(T* array, size_t size) {
  T result = T();
  for (size_t i = 0; i < size; ++i) {
    result += array[i];
  }
  return result;
}

В этом примере функция sum использует параметр шаблона T для указания типа элементов в массиве. Он инициализирует переменную result значением по умолчанию типа T и перебирает массив, накапливая сумму.

Теперь давайте воспользуемся функцией sum с двумя разными типами массивов: int и double.

int intArray[] = {1, 2, 3, 4, 5};
double doubleArray[] = {1.1, 2.2, 3.3, 4.4, 5.5};
int intSum = sum(intArray, sizeof(intArray) / sizeof(intArray[0]));
double doubleSum = sum(doubleArray, sizeof(doubleArray) / sizeof(doubleArray[0]));

В этом коде мы вызываем функцию sum дважды, один раз с массивом целых чисел и один раз с массивом двойных значений. Компилятор C++ генерирует две специализированные версии функции sum для int и double во время компиляции.

Ключевым моментом здесь является то, что функция sum предоставляет высокоуровневую абстракцию для вычисления суммы массива, а благодаря шаблонам компилятор генерирует эффективный код для каждого конкретного типа. Сама абстракция не создает накладных расходов во время выполнения. Сгенерированный код для каждой специализации функции sum будет столь же эффективным, как если бы вы вручную написали отдельный код для массивов int и double.

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

Стоит отметить, что абстракция с нулевой стоимостью не ограничивается шаблонами. Это относится и к другим функциям C++, таким как классы, наследование и полиморфизм. Цель всегда состоит в том, чтобы включить абстракции высокого уровня без ущерба для производительности во время выполнения.

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

НО вот загвоздка

По словам Чендлера Каррута, в 2019 году он сказал Нет абстракций с нулевой стоимостью.

Я не буду вдаваться здесь в подробности. Я оставлю эту задачу вам..

Удачи, товарищи программисты и гики.