Last updated:2026-10-12
C++20 [[likely]] and [[unlikely]]¶
C++20 introduced the two likelihood attributes [[likely]] and [[unlikely]], which give the compiler optimization hints that the corresponding code path is likely/unlikely to be executed.
At first glance, these seem like a rather nice pair of attributes: let the compiler optimize and thereby gain performance. But that is not actually the case.
The C++ standard draft explicitly states: Excessive usage of either of these attributes is liable to result in performance degradation.
That is: overusing either attribute may well degrade performance.
So in which situations are they useful, and in which are they unnecessary?
This article offers my own take.
1. Principles¶
Follow these principles when using them:
- Use them with care: only apply these attributes when you are certain that a branch or path is extremely likely — or extremely unlikely — to be taken at runtime.
For example, the code below checks whether a value is greater than 0. If the input data cannot guarantee that value is very probably (or certainly) greater than 0, then the optimization below is meaningless.
if (value > 0) [[likely]] {
std::cout << "Value is positive: " << value << std::endl;
} else [[unlikely]] {
std::cout << "Value is non-positive: " << value << std::endl;
}
For example, here is unlikely as used in the standard library. A member function of the _Variant_storage struct uses this attribute: the probability of being invalid is extremely low, so it can be marked with unlikely.
- Mark the dominant path: apply the attribute only on the dominant execution path, not on every possible path.
For example, in the if statement below two equivalent branches are marked likely, which does not mean much.
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. Example¶
Finally, a very common example: vector's at. We know it checks whether the index exceeds the vector's size, and that probability is fairly low, so we can use unlikely, for example:
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];
}
Related Topics¶
- Getting Started with C++20 Coroutines | C++那些事
- C++20 channel in Practice | C++那些事
- C++20 Concepts | C++那些事
- C++20 constexpr and the Comma Expression | C++那些事
- C++20 Byte Order (endian) | C++那些事
- C++20 Lambda Expressions (Part 1) | C++那些事
- C++20 Modules | C++那些事
- C++20 Ranges Library | C++那些事
- C++20 std::span Design and Pitfalls | C++那些事
- A Guide to C++20 New Features | C++那些事