コンテンツにスキップ

最終更新: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.

つまり、どちらかの属性を過度に使うとパフォーマンス低下を招くおそれがあります。

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

では、どんな場合に有用で、どんな場合には不要なのでしょうか?

本記事では私の見解を述べます。

1.原則

使用時には以下の原則に従うべきです:

  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 でマークできます。

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

  // do something
}
  1. 支配的パスをマークする:すべての可能性のあるパスではなく、支配的な実行パスにだけ属性を使います。

例えば:次の 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];
}

関連トピック

コメント