Saltar a contenido

Última actualización:2026-10-12

C++20 [[likely]] y [[unlikely]]

C++20 introdujo los dos atributos de probabilidad [[likely]] y [[unlikely]], que dan al compilador pistas de optimización indicando que la ruta de código correspondiente probablemente se ejecute o no.

A primera vista parece un par de atributos muy útiles, que permiten mejorar el rendimiento mediante la optimización del compilador. Pero la realidad no es así.

En el borrador del estándar de C++ se menciona explícitamente: Excessive usage of either of these attributes is liable to result in performance degradation.

Es decir: el uso excesivo de cualquiera de estos atributos puede degradar el rendimiento.

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

Entonces, ¿en qué situaciones resultan útiles y en cuáles no hacen falta?

En este artículo doy mi punto de vista.

1.Principios

Su uso debería seguir estos principios:

  1. Usarlos con cautela: emplea estos atributos solo cuando estés seguro de que una rama o ruta es extremadamente probable o improbable en tiempo de ejecución.

Por ejemplo: en la siguiente comprobación de si un value es mayor que 0, si los datos de entrada no garantizan que value sea mayor que 0 con alta probabilidad o con total certeza, la siguiente optimización no tiene ningún sentido.

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

Por ejemplo: un uso de unlikely en la biblioteca estándar. Una función miembro del struct _Variant_storage usa este atributo; la probabilidad de que sea inválido es muy baja, por lo que puede marcarse con unlikely.

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

  // do something
}
  1. Marcar la ruta dominante: usa los atributos solo en la ruta de ejecución dominante, no en todas las rutas posibles.

Por ejemplo: si un if marca dos ramas equivalentes como likely, el sentido es escaso.

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.Ejemplo

Para terminar, un ejemplo bastante común: el at de un vector; sabemos que comprueba si se supera el size del vector, algo con probabilidad baja, así que podemos usar unlikely, por ejemplo:

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];
}

Temas relacionados

Comentarios