Ir para o conteúdo

Última atualização:2026-10-12

[[likely]] e [[unlikely]] no C++20

O C++20 introduziu os dois atributos de probabilidade [[likely]] e [[unlikely]], que dão dicas de otimização ao compilador, indicando que o caminho de código correspondente provavelmente será/não será executado.

À primeira vista, parecem atributos bastante úteis: por meio da otimização do compilador, melhoraria o desempenho. Mas a realidade não é bem assim.

O rascunho do padrão C++ menciona explicitamente: Excessive usage of either of these attributes is liable to result in performance degradation.

Ou seja: o uso excessivo de qualquer um desses atributos pode causar degradação de desempenho.

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

Então, em que situações eles são úteis e em que situações não são necessários?

Este artigo apresenta meu ponto de vista.

1.Princípios

Ao usar, devem-se seguir os princípios a seguir:

  1. Usar com cautela: use esses atributos apenas quando tiver certeza de que um ramo ou caminho é extremamente provável ou improvável em tempo de execução.

Por exemplo: a verificação abaixo diz se um value é maior que 0; se os dados de entrada não garantem que value seja muito provavelmente/sempre maior que 0, essa otimização não faz o menor 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 exemplo: um caso de uso de unlikely na biblioteca padrão. Uma função-membro da estrutura _Variant_storage usa esse atributo; a probabilidade de ser inválido é baixíssima, por isso é possível usar unlikely para marcá-lo.

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

  // do something
}
  1. Marcar o caminho dominante: use os atributos apenas no caminho de execução dominante, e não em todos os caminhos possíveis.

Por exemplo: se um if marca dois likely equivalentes, como o abaixo, isso não faz muito sentido.

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

Por fim, um exemplo bem comum: o at do vector. Sabemos que ele verifica se o índice excede o size do vector; como essa probabilidade é baixa, podemos usar unlikely; por exemplo:

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

Tópicos relacionados

Comentários