C++ attribute: likely, unlikely (since C++20)
| 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 | ||||||||||||||||
|
||||||||||||||||
| 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 | ||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(C++23)
|
||||
|
(C++11)
(until C++26)
|
||||
|
(C++14)
|
||||
|
(C++17)
|
||||
|
(C++26)
|
||||
|
likely
(C++20)
|
||||
|
(C++17)
|
||||
|
(C++17)
|
||||
|
(C++11)
|
||||
|
(C++20)
|
||||
|
(TM TS)
|
||||
|
unlikely
(C++20)
|
컴파일러가 해당 문장을 포함하는 실행 경로가 그러한 문장을 포함하지 않는 다른 실행 경로보다 더 많거나 적을 가능성에 대해 최적화할 수 있도록 허용합니다.
목차 |
구문
[
[
likely
]
]
|
(1) | ||||||||
[
[
unlikely
]
]
|
(2) | ||||||||
설명
이러한 특성은 레이블과 선언문이 아닌 문에 적용될 수 있습니다. 동일한 레이블이나 문에 동시에 적용될 수 없습니다.
실행 경로는 해당 레이블로의 점프를 포함하는 경우에만 해당 레이블을 포함하는 것으로 간주됩니다:
int f(int i) { switch (i) { case 1: [[fallthrough]]; [[likely]] case 2: return 1; } return 2; }
i == 2 는 다른 i 값들보다 더 발생 가능성이 높은 것으로 간주되지만, [ [ likely ] ] 속성은 i == 1 경우에는 아무런 영향을 미치지 않습니다. 비록 해당 경우가 case 2 : 레이블을 통해 폴스루(fall through)되더라도 마찬가지입니다.
예제
#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{}; // 사이드 이펙트를 보장함 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) ? "equal" : "차이점") << '\n'; auto benchmark = [](auto fun, auto rem) { const auto start = std::chrono::high_resolution_clock::now **변경 없음** - C++ 특정 용어와 코드 태그 내 내용은 번역하지 않음(); for (auto size{1ULL}; size != 10'000'000ULL; ++size) sink = fun(gen_random()); const std::chrono::duration (번역 참고: HTML 태그와 속성은 번역하지 않았으며, C++ 관련 용어(std::chrono::duration)는 원문 그대로 유지했습니다)<double> diff = std::chrono::high_resolution_clock::now() - start; std::cout << "시간: " << std::fixed << std::setprecision(6) << diff.count() << " 초 " << rem << std::endl; }; benchmark(with_attributes::cos, "(속성 포함)"); benchmark(no_attributes::cos, "(속성 없음)"); benchmark([](double t) { return std::cos(t); }, "(std::cos)"); }
가능한 출력:
x = 0.125 0.99219766722932900560039115589461289346218109130859375 0.99219766722932900560039115589461289346218109130859375 동일함 x = 0.25 0.96891242171064473343022882545483298599720001220703125 0.96891242171064473343022882545483298599720001220703125 동일함 x = 0.5 0.8775825618903727587394314468838274478912353515625 0.8775825618903727587394314468838274478912353515625 동일함 x = 1.490116119384765625e-08 0.99999999999999988897769753748434595763683319091796875 0.99999999999999988897769753748434595763683319091796875 동일함 시간: 0.579122 초 (속성 포함) 시간: 0.722553 초 (속성 없음) 시간: 0.425963 초 (std::cos)
참고문헌
- C++23 표준(ISO/IEC 14882:2024):
-
- 9.12.7 가능성 속성 [dcl.attr.likelihood]
- C++20 표준(ISO/IEC 14882:2020):
-
- 9.12.6 가능성 속성 [dcl.attr.likelihood]