Перейти к содержанию

Последнее обновление:2026-10-12

[[likely]] и [[unlikely]] в C++20

В C++20 появились два атрибута вероятности — [[likely]] и [[unlikely]]; они дают компилятору подсказки для оптимизации, указывая, что соответствующая ветка кода, скорее всего, будет/не будет выполнена.

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

В черновике стандарта C++ прямо сказано: Excessive usage of either of these attributes is liable to result in performance degradation.

То есть: чрезмерное использование любого из этих атрибутов может привести к снижению производительности.

https://eel.is/c++draft/dcl.attr.likelihood#note-2

Так когда же они действительно полезны, а когда не нужны?

В этой статье изложу свою точку зрения.

1.Принципы

При использовании следует придерживаться таких принципов:

  1. Применяйте с осторожностью: используйте эти атрибуты, только если вы точно уверены, что конкретная ветка или путь крайне вероятны или невероятны во время выполнения.

Например: ниже проверяется, больше ли value нуля; если во входных данных нельзя гарантировать, что value с высокой вероятностью/точно больше 0, то такая оптимизация не имеет никакого смысла.

if (value > 0) [[likely]] {
    std::cout << "Value is positive: " << value << std::endl;
} else [[unlikely]] {
    std::cout << "Value is non-positive: " << value << std::endl;
}

Например: пример использования unlikely в стандартной библиотеке. Функция-член в структуре _Variant_storage использует этот атрибут, поскольку вероятность невалидности крайне мала, поэтому её можно пометить unlikely.

constexpr void
_M_reset()
{
  if (!_M_valid()) [[unlikely]]
    return;

  // do something
}
  1. Помечайте доминирующий путь: используйте атрибуты только на доминирующем пути выполнения, а не на всех возможных путях.

Например: если в приведённом ниже if помечены два равнозначных likely, то смысла в этом немного.

if (value > 10) [[likely]] {
    // 主导路径:值大于 10
    std::cout << "Value is greater than 10: " << value << std::endl;
} else if (value > 5) [[likely]] {
    // 次主导路径:值大于 5 且小于等于 10
    std::cout << "Value is greater than 5 but less than or equal to 10: " << value << std::endl;
} else [[unlikely]] {
    // 较少出现的路径:值小于等于 5
    std::cout << "Value is 5 or less: " << value << std::endl;
}

2.Пример

Напоследок приведу довольно распространённый пример — at у vector: как мы знаем, она проверяет выход за пределы size вектора, и вероятность этого сравнительно низка, поэтому можно использовать unlikely, например:

int& at(std::vector<int>& vec, std::size_t i) {
  if (i >= vec.size()) [[unlikely]] {
      throw std::out_of_range("Out of bounds access");
  }
  return vec[i];
}

Похожие темы

Комментарии