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) |
Allow the compiler to optimize for the case where paths of execution including that statement are more or less likely than any alternative path of execution that does not include such a statement.
Contents |
[[likely]] | (1) | ||||||||
[[unlikely]] | (2) | ||||||||
These attributes may be applied to labels and statements (other than declaration-statements). They may not be simultaneously applied to the same label or statement.
A path of execution is deemed to include a label if and only if it contains a jump to that label:
int f(int i){switch(i){case1:[[fallthrough]];[[likely]]case2:return1;}return2;}
i==2 is considered more likely than any other value ofi
, but the[[likely]] has no effect on thei==1 case even though it falls through thecase2: label.
#include <chrono>#include <cmath>#include <iomanip>#include <iostream>#include <random> namespace with_attributes{constexprdouble pow(double x,longlong n)noexcept{if(n>0)[[likely]]return x* pow(x, n-1);else[[unlikely]]return1;}constexprlonglong fact(longlong n)noexcept{if(n>1)[[likely]]return n* fact(n-1);else[[unlikely]]return1;}constexprdouble cos(double x)noexcept{constexprlonglong 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{constexprdouble pow(double x,longlong n)noexcept{if(n>0)return x* pow(x, n-1);elsereturn1;}constexprlonglong fact(longlong n)noexcept{if(n>1)return n* fact(n-1);elsereturn1;}constexprdouble cos(double x)noexcept{constexprlonglong 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{staticstd::random_device rd;staticstd::mt19937 gen(rd());staticstd::uniform_real_distribution<double> dis(-1.0,1.0);return dis(gen);} volatiledouble sink{};// ensures a side effect int main(){for(constauto 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":"differ")<<'\n'; auto benchmark=[](auto fun,auto rem){constauto start=std::chrono::high_resolution_clock::now();for(auto size{1ULL}; size!=10'000'000ULL;++size) sink= fun(gen_random());conststd::chrono::duration<double> diff=std::chrono::high_resolution_clock::now()- start;std::cout<<"Time: "<<std::fixed<<std::setprecision(6)<< diff.count()<<" sec "<< rem<<std::endl;}; benchmark(with_attributes::cos,"(with attributes)"); benchmark(no_attributes::cos,"(without attributes)"); benchmark([](double t){returnstd::cos(t);},"(std::cos)");}
Possible output:
x = 0.1250.992197667229329005600391155894612893462181091308593750.99219766722932900560039115589461289346218109130859375equalx = 0.250.968912421710644733430228825454832985997200012207031250.96891242171064473343022882545483298599720001220703125equalx = 0.50.87758256189037275873943144688382744789123535156250.8775825618903727587394314468838274478912353515625equalx = 1.490116119384765625e-080.999999999999999888977697537484345957636833190917968750.99999999999999988897769753748434595763683319091796875equalTime: 0.579122 sec (with attributes)Time: 0.722553 sec (without attributes)Time: 0.425963 sec (std::cos)