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 | ||||||||||||||||
Renders the entire program meaningless if certain rules of the language are violated.
Contents |
The C++ standard precisely defines theobservable behavior of every C++ program that does not fall into one of the following classes:
| (since C++26) |
| (since C++11) |
Because correct C++ programs are free of undefined behavior, compilers may produce unexpected results when a program that actually has UB is compiled with optimization enabled:
For example,
int foo(int x){return x+1> x;// either true or UB due to signed overflow}
may be compiled as (demo)
foo(int): mov eax,1 ret
int table[4]={};bool exists_in_table(int v){// return true in one of the first 4 iterations or UB due to out-of-bounds accessfor(int i=0; i<=4; i++)if(table[i]== v)returntrue;returnfalse;}
May be compiled as (demo)
exists_in_table(int): mov eax,1 ret
std::size_t f(int x){std::size_t a;if(x)// either x nonzero or UB a=42;return a;}
May be compiled as (demo)
f(int): mov eax,42 ret
The output shown was observed on an older version of gcc
Possible output:
p is truep is false
int f(){bool b=true;unsignedchar* p=reinterpret_cast<unsignedchar*>(&b);*p=10;// reading from b is now UBreturn b==0;}
May be compiled as (demo)
f(): mov eax,11 ret
The examples demonstrate reading from the result of dereferencing a null pointer.
int foo(int* p){int x=*p;if(!p)return x;// Either UB above or this branch is never takenelsereturn0;} int bar(){int* p= nullptr;return*p;// Unconditional UB}
may be compiled as (demo)
foo(int*): xor eax, eax retbar(): ret
Choose clang to observe the output shown
#include <cstdlib>#include <iostream> int main(){int* p=(int*)std::malloc(sizeof(int));int* q=(int*)std::realloc(p, sizeof(int));*p=1;// UB access to a pointer that was passed to realloc*q=2;if(p== q)// UB access to a pointer that was passed to reallocstd::cout<<*p<<*q<<'\n';}
Possible output:
12
Choose clang or the latest gcc to observe the output shown.
#include <iostream> bool fermat(){constint max_value=1000; // Non-trivial infinite loop with no side effects is UBfor(int a=1, b=1, c=1;true;){if(((a* a* a)==((b* b* b)+(c* c* c))))returntrue;// disproved :() a++;if(a> max_value){ a=1; b++;}if(b> max_value){ b=1; c++;}if(c> max_value) c=1;} returnfalse;// not disproved} int main(){std::cout<<"Fermat's Last Theorem "; fermat()?std::cout<<"has been disproved!\n":std::cout<<"has not been disproved.\n";}
Possible output:
Fermat's Last Theorem has been disproved!
Note that compilers are permitted to extend the language in ways that give meaning to ill-formed programs. The only thing C++ standard requires in such cases is a diagnostic message (compiler warning), unless the program was "ill-formed no diagnostic required".
For example, unless language extensions are disabled via--pedantic-errors
, GCC will compile the following examplewith only a warning even though itappears in the C++ standard as an example of an "error" (see alsoGCC Bugzilla #55783)
#include <iostream> // Example tweak, do not use constantdouble a{1.0}; // C++23 standard, §9.4.5 List-initialization [dcl.init.list], Example #6:struct S{// no initializer-list constructors S(int,double,double);// #1 S();// #2// ...}; S s1={1,2,3.0};// OK, invoke #1S s2{a,2,3};// error: narrowingS s3{};// OK, invoke #2// — end example] S::S(int,double,double){}S::S(){} int main(){std::cout<<"All checks have passed.\n";}
Possible output:
main.cpp:17:6: error: type 'double' cannot be narrowed to 'int' in initializer ⮠list [-Wc++11-narrowing]S s2{a, 2, 3}; // error: narrowing ^main.cpp:17:6: note: insert an explicit cast to silence this issueS s2{a, 2, 3}; // error: narrowing ^ static_cast<int>( )1 error generated.
Extended content |
---|
|
[[assume(expression)]] (C++23) | specifies that theexpression will always evaluate totrue at a given point (attribute specifier)[edit] |
[[indeterminate]] (C++26) | specifies that an object has an indeterminate value if it is not initialized (attribute specifier)[edit] |
(C++23) | marks unreachable point of execution (function)[edit] |
C documentation forUndefined behavior |