Ú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.
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:
- 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.
- 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¶
- Introdução às corrotinas no C++20 | C++那些事
- Prática com channel no C++20 | C++那些事
- Concepts (conceitos) no C++20 | C++那些事
- constexpr e a expressão vírgula no C++20 | C++那些事
- Ordem de bytes (endian) no C++20 | C++那些事
- Expressões Lambda no C++20 (parte 1) | C++那些事
- Módulos (Modules) no C++20 | C++那些事
- Biblioteca Ranges do C++20 | C++那些事
- Design e armadilhas do std::span no C++20 | C++那些事
- Guia dos novos recursos do C++20 | C++那些事