Последнее обновление: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.
То есть: чрезмерное использование любого из этих атрибутов может привести к снижению производительности.
Так когда же они действительно полезны, а когда не нужны?
В этой статье изложу свою точку зрения.
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.
- Помечайте доминирующий путь: используйте атрибуты только на доминирующем пути выполнения, а не на всех возможных путях.
Например: если в приведённом ниже 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];
}
Похожие темы¶
- Введение в корутины C++20 | C++那些事
- Практика с channel в C++20 | C++那些事
- Концепции Concepts в C++20 | C++那些事
- constexpr и оператор «запятая» в C++20 | C++那些事
- Порядок байтов endian в C++20 | C++那些事
- Лямбда-выражения в C++20 (часть 1) | C++那些事
- Модули Modules в C++20 | C++那些事
- Библиотека Ranges в C++20 | C++那些事
- Дизайн и подводные камни std::span в C++20 | C++那些事
- Обзор новых возможностей C++20 | C++那些事