最終更新:2026-10-12
C++20 [[likely]] と [[unlikely]]¶
C++20 は [[likely]] と [[unlikely]] という2つの可能性属性を導入しました。これらはコンパイラに最適化のヒントを与え、対応するコードパスが実行される/されない可能性が高いことを示します。
一見すると、コンパイラ最適化によってパフォーマンスを高められる、とても良さそうな属性に思えます。しかし実際はそうではありません。
C++ 規格草案には次のように明記されています:Excessive usage of either of these attributes is liable to result in performance degradation.
つまり、どちらかの属性を過度に使うとパフォーマンス低下を招くおそれがあります。
では、どんな場合に有用で、どんな場合には不要なのでしょうか?
本記事では私の見解を述べます。
1.原則¶
使用時には以下の原則に従うべきです:
- 慎重に使う:ある分岐やパスが実行時に極めて可能性が高い/低いと確信できる場合にだけ、これらの属性を使います。
例えば:次のコードは value が 0 より大きいかを判定します。入力データから 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 判定では2つの等価な 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.例¶
最後に比較的よくある例を挙げます。それは vector の at です。ご存知の通り、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++那些事
- C++20 channel 実践 | C++那些事
- C++20 Concepts コンセプト | C++那些事
- C++20 constexpr とカンマ式 | C++那些事
- C++20 バイトオーダー endian | C++那些事
- C++20 Lambda 式(前編) | C++那些事
- C++20 モジュール Modules | C++那些事
- C++20 Ranges ライブラリ | C++那些事
- C++20 std::span の設計と落とし穴 | C++那些事
- C++20 新機能ガイド | C++那些事