static
(C89) / (C++98)
-
Static has two fundamental effects, depending on where it appears:
-
Changes storage duration (object lives for the entire program).
-
Changes linkage (name is visible only within the translation unit).
-
-
Global variable :
-
Internal linkage + static storage duration
-
-
Local variable :
-
Static storage duration
-
-
Global function :
-
Simply makes the function private to the Translation Unit.
-
The linker does not export its symbol.
-
Other translation units cannot call it, even if they declare it with
extern. -
If a function is only used inside tht TU, making it static expresses that intent.
-
Because the compiler knows nobody outside the Translation Unit can call the function, it can sometimes:
-
inline it more aggressively
-
remove it entirely if unused
-
specialize it
-
rename or merge it freely.
-
-
In C :
-
It's the traditional way to give a function internal linkage.
-
-
In C++ :
-
It's preferred to use Anonymous Namespaces for the same result.
-
-
-
Class data member (C++) :
-
One variable shared by all instances.
-
-
Class member function (C++) :
-
No this pointer; callable without an object.
-
Makes the function now belong to the class, not to the instance.
-
export
(C++98->C++20)
-
C++98:
-
Exported templates
-
The feature failed, as it turned out to be extremely difficult to implement.
-
A compiler had to:
-
track template definitions across translation units,
-
instantiate templates later,
-
manage complex dependency information.
-
-
Almost no compiler implemented it.
-
-
C++11:
-
The original
exportkeyword remained reserved, but the exported-template feature was effectively dead.
-
-
C++20:
-
Completely repurposed
export. -
Now it exports names from a module.
-
It means "This declaration is visible outside the module. Non-exported declarations remain internal"
export module math; export int add(int a, int b) { return a + b; }-
In another file:
import math; int x = add(3, 4); -
-
exportvsextern:-
extern-
Declares that a symbol is defined elsewhere (linkage).
-
-
export(C++20)-
Makes a declaration part of a module's public interface.
-
-
explicit
(C++98)
-
Its purpose is to prevent the compiler from performing implicit conversions through constructors or conversion operators.
-
C++98 — introduced
explicitfor constructors.-
Without
explicit:struct String { String(const char* s) {} }; void print(String s); int main() { print("hello"); // OK } -
With
explicit:struct String { explicit String(const char* s) {} }; void print(String s); int main() { print("hello"); // Error print(String("hello")); // OK }struct Vec2 { explicit Vec2(float v) : x(v), y(v) {} float x, y; }; Vec2 a(5.0f); // OK Vec2 b = 5.0f; // Error-
Direct initialization is allowed, but copy initialization is not, as that would require an implicit conversion.
-
-
-
C++11 — extended it to conversion operators:
explicit operator bool() const;-
Without
explicit:struct File { operator bool() const { return true; } }; File f; if (f) { } // OK bool b = f; // OK int x = f; // Also possible through bool -> int -
With
explicit:struct File { explicit operator bool() const { return true; } }; File f; if (f) { } // OK (special case) bool b = f; // Error bool b2 = static_cast<bool>(f); // OK
-
-
C++20 — introduced conditional
explicit:template<typename T> explicit(sizeof(T) > 4) MyType(T);-
The constructor is explicit only if the constant expression evaluates to true.
-
[[assume(expression)]]
(C++23)
-
Gives optimizer a condition assumed to be true.
-
Undefined behavior if false at runtime.
[[assume(x > 0)]];
-
Low-level optimization hint.
-
Vendor equivalents (both languages):
-
__builtin_assume -
__assume(MSVC)
-
-
Used to eliminate bounds checks and unreachable branches.
_Static_assert
(C11) /
static_assert
(C++11)
Compile-time assertion (not attribute).
_Static_assert(sizeof(int) == 4, "Unexpected size");
constexpr
(C++11)
-
Allows evaluation at compile time.
-
The compiler may compute the result during compilation.
-
Used for:
-
lookup tables
-
compile-time constants
-
metaprogramming
-
constexpr int square(int x) {
return x * x;
}
int a = square(4);
const
(C89, C++98)
-
constis not the same guarantee asconstexprin C++. The key difference is:-
const→ read-only (may or may not be compile-time) -
constexpr→ must be compile-time
-
const int MAX = 64;
-
You cannot
modifyMAX -
But it is not guaranteed to be a compile-time constant in all contexts
consteval
(C++20)
-
.
constinit
(C++20)
-
.
_Noreturn
(C11),
[[noreturn]]
(C++11)
-
Indicates a function never returns.
[[noreturn]] void fatal();
-
They are semantic guarantees, not just documentation. They can affect code generation.
-
They state that a function:
-
never returns normally
-
either calls exit, abort, longjmp, or loops forever
-
reaching the end is undefined behavior
-
-
The compiler:
-
does not require a return
-
removes code after the call
-
may remove stack cleanup logic
-
restrict
(C99)
-
For the lifetime of the pointer the object it points to is accessed only through that pointer (or a value directly derived from it).
-
Enables aliasing optimizations.
-
Tells compiler pointers do not alias.
-
Very significant in hot loops:
-
enables vectorization
-
enables load/store reordering
-
reduces reloads from memory
-
improves auto-SIMD generation
-
-
Without restrict, compiler must conservatively assume aliasing.
-
Incorrect use causes undefined behavior and real miscompilations.
void f(int * restrict p);
-
C++ has no standard equivalent (vendors support __restrict).
[[no_unique_address]]
(C++20)
-
Allows a non-static data member (typically empty type) to occupy no storage.
struct Empty {};
struct S {
int x;
[[no_unique_address]] Empty e;
};
-
Without it:
-
emay consume 1 byte
-
-
With it:
-
ecan overlap with padding -
object size may shrink
-
-
Optimization impact
-
reduces object size
-
improves cache density
-
improves container packing
-
[[reproducible]]
(C23)
-
Guarantees that the function:
-
has no observable side effects
-
depends only on its arguments and possibly global state
-
produces consistent results
-
[[reproducible]]
int pure_compute(int x);
-
Vendor equivalents in both languages:
-
__attribute__((pure))
-
-
Optimization impact
-
Allows:
-
common subexpression elimination
-
redundant call elimination
-
hoisting out of loops
-
reordering relative to unrelated side effects
-
-
-
The compiler may transform:
int a = f(10); int b = f(10); -
into:
int a = f(10); int b = a;
[[unsequenced]]
(C23)
-
Stronger than [[reproducible]].
-
Indicates:
-
no side effects
-
no synchronization
-
no inter-thread interaction
-
can be evaluated in unsequenced context
-
[[unsequenced]]
int fast_math(int x);
-
Vendor equivalents in both languages:
-
__attribute__((const))
-
-
Optimization impact
-
Allows:
-
aggressive reordering
-
call merging
-
vectorization
-
evaluation in arbitrary order
-
removal if result unused
-
-