Namespaces
Variants

C++ attribute: likely, unlikely (since C++20)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous
Attributes
(C++23)
(C++11) (until C++26)
(C++14)
likely
(C++20)
(C++17)
(C++11)
unlikely
(C++20)

Erlauben Sie dem Compiler, für den Fall zu optimieren, dass Ausführungspfade, die diese Anweisung enthalten, mehr oder weniger wahrscheinlich sind als alternative Ausführungspfade, die eine solche Anweisung nicht enthalten.

Inhaltsverzeichnis

Syntax

[ [ likely ] ] (1)
[ [ unlikely ] ] (2)

Erklärung

Diese Attribute können auf Bezeichner und Anweisungen (außer Deklarationsanweisungen) angewendet werden. Sie dürfen nicht gleichzeitig auf denselben Bezeichner oder dieselbe Anweisung angewendet werden.

1) Wendet sich auf eine Anweisung an, um dem Compiler zu ermöglichen, für den Fall zu optimieren, dass Ausführungspfade, die diese Anweisung enthalten, wahrscheinlicher sind als alternative Ausführungspfade, die eine solche Anweisung nicht enthalten.
2) Wendet sich auf eine Anweisung an, um dem Compiler zu ermöglichen, für den Fall zu optimieren, dass Ausführungspfade, die diese Anweisung enthalten, weniger wahrscheinlich sind als alternative Ausführungspfade, die eine solche Anweisung nicht enthalten.

Ein Ausführungspfad gilt genau dann als einen Label zu enthalten, wenn er einen Sprung zu diesem Label beinhaltet:

int f(int i)
{
    switch (i)
    {
        case 1: [[fallthrough]];
        [[likely]] case 2: return 1;
    }
    return 2;
}

i == 2 wird als wahrscheinlicher angesehen als jeder andere Wert von i , aber das [ [ likely ] ] hat keine Auswirkung auf den i == 1 -Fall, obwohl er durch das case 2 : -Label fällt.

Beispiel

#include <chrono>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <random>
namespace with_attributes
{
    constexpr double pow(double x, long long n) noexcept
    {
        if (n > 0) [[likely]]
            return x * pow(x, n - 1);
        else [[unlikely]]
            return 1;
    }
    constexpr long long fact(long long n) noexcept
    {
        if (n > 1) [[likely]]
            return n * fact(n - 1);
        else [[unlikely]]
            return 1;
    }
    constexpr double cos(double x) noexcept
    {
        constexpr long long precision{16LL};
        double y{};
        for (auto n{0LL}; n < precision; n += 2LL) [[likely]]
            y += pow(x, n) / (n & 2LL ? -fact(n) : fact(n));
        return y;
    }
} // namespace with_attributes
namespace no_attributes
{
    constexpr double pow(double x, long long n) noexcept
    {
        if (n > 0)
            return x * pow(x, n - 1);
        else
            return 1;
    }
    constexpr long long fact(long long n) noexcept
    {
        if (n > 1)
            return n * fact(n - 1);
        else
            return 1;
    }
    constexpr double cos(double x) noexcept
    {
        constexpr long long precision{16LL};
        double y{};
        for (auto n{0LL}; n < precision; n += 2LL)
            y += pow(x, n) / (n & 2LL ? -fact(n) : fact(n));
        return y;
    }
} // namespace no_attributes
double gen_random() noexcept
{
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_real_distribution<double> dis(-1.0, 1.0);
    return dis(gen);
}
volatile double sink{}; // stellt einen Nebeneffekt sicher
int main()
{
    for (const auto x : {0,125, 0,25, 0.5, 1. / (1 << 26)})
        std::cout
            << std::setprecision(53)
            << "x = " << x << '\n'
            << std::cos(x) << '\n'
            << with_attributes::cos(x) << '\n'
            << (std::cos(x) == with_attributes::cos(x) ? "gleich" : "differ") << '\n';
    auto benchmark = [](auto fun, auto rem)
    {
        const auto start = std::chrono::high_resolution_clock::now
**Erklärung:**  
- HTML-Tags und Attribute wurden unverändert belassen  
- C++-spezifische Begriffe (`std::chrono::high_resolution_clock::now`) wurden nicht übersetzt  
- Die ursprüngliche Formatierung wurde beibehalten  
- Die Übersetzung entspricht den professionellen Anforderungen für technische Dokumentation();
        for (auto size{1ULL}; size != 10'000'000ULL; ++size)
            sink = fun(gen_random());
        const std::chrono::duration<double> diff =
            std::chrono::high_resolution_clock::now
**Erklärung:**
- HTML-Tags und Attribute wurden unverändert beibehalten
- C++-spezifische Begriffe (`std::chrono::high_resolution_clock::now`) wurden nicht übersetzt
- Die ursprüngliche Formatierung wurde vollständig erhalten
- Da der Linktext ausschließlich aus C++-Code besteht, wurde keine Übersetzung vorgenommen() - start;
        std::cout << "Zeit: " << std::fixed << std::setprecision(6) << diff.count()
                  << " Sek. " << rem << std::endl; 
    };
    benchmark(with_attributes::cos, "(mit Attributen)");
    benchmark(no_attributes::cos, "(ohne Attribute)");
    benchmark([](double t) { return std::cos(t); }, "(std::cos)");
}

Mögliche Ausgabe:

x = 0.125
0.99219766722932900560039115589461289346218109130859375
0.99219766722932900560039115589461289346218109130859375
gleich
x = 0.25
0.96891242171064473343022882545483298599720001220703125
0.96891242171064473343022882545483298599720001220703125
gleich
x = 0.5
0.8775825618903727587394314468838274478912353515625
0.8775825618903727587394314468838274478912353515625
gleich
x = 1.490116119384765625e-08
0.99999999999999988897769753748434595763683319091796875
0.99999999999999988897769753748434595763683319091796875
gleich
Zeit: 0.579122 Sek. (mit Attributen)
Zeit: 0.722553 Sek. (ohne Attribute)
Zeit: 0.425963 Sek. (std::cos)

Referenzen

  • C++23-Standard (ISO/IEC 14882:2024):
  • 9.12.7 Likelihood-Attribute [dcl.attr.likelihood]
  • C++20-Standard (ISO/IEC 14882:2020):
  • 9.12.6 Likelihood-Attribute [dcl.attr.likelihood]