Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The * token in C++ is a context-dependent symbol that serves five distinct syntactic and semantic roles: a type modifier for pointer declarations, a type modifier for pointer-to-member declarations, a unary indirection (dereference) operator, a binary arithmetic multiplication operator, and a lambda capture-by-copy specifier. The compiler determines the specific role based on the lexical context of the token.

1. Pointer Declaration (Type Modifier)

When used in a declaration context, * acts as a type modifier that transforms a base type T into a compound type “pointer to T”.
// Syntax
T* declarator;
T * declarator;
T *declarator;
Mechanics:
  • Binding: In C++ grammar, the * token is a ptr-operator that forms part of the declarator. It modifies the individual declarator it belongs to (specifically the unqualified-id or variable name), rather than the shared base type specifier. In the declaration int* a, b;, a is of type int* (pointer to int), while b is of type int.
  • CV-Qualifiers: The * can be followed by const or volatile qualifiers to modify the pointer itself, rather than the pointed-to type (e.g., T* const declares a constant pointer to a mutable T).
  • Multiple Indirection: Multiple * tokens can be chained to declare pointers to pointers (e.g., T**).

2. Pointer-to-Member Declaration (Type Modifier)

When combined with a class scope resolution operator, * declares a pointer to a non-static class member. This is a distinct compound type with different semantics than a standard memory pointer.
// Syntax
T ClassName::* declarator;
Mechanics:
  • Representation: A pointer-to-member does not hold a direct memory address; rather, it holds an offset or an internal representation that identifies a specific member within any instance of ClassName.
  • Access: Dereferencing a pointer-to-member requires an object instance and is performed using the distinct .* or ->* operators, not the unary * operator.

3. Unary Indirection Operator (Dereference)

When used as a prefix unary operator, * performs indirection. It accesses the memory address held by its operand and evaluates to an lvalue representing the object or function at that address.
// Syntax
*expression
Mechanics:
  • Operand Requirements: The operand must be an expression of a pointer type (pointer to object or pointer to function).
  • Return Category: The result is an lvalue expression of the pointed-to type. If the operand points to an object of a non-const type, the resulting lvalue is modifiable and can be assigned to. If the operand points to a function, the result is a function lvalue, which is not a modifiable lvalue and cannot be assigned to, regardless of const qualification.
  • Undefined Behavior (UB) and Exceptions: Evaluating the indirection operator on an uninitialized pointer, a dangling pointer, or a null pointer invokes undefined behavior. There is exactly one exception: if the operand is a null pointer to a polymorphic type and is evaluated within a typeid expression (e.g., typeid(*p)), the runtime safely throws a std::bad_typeid exception. If the pointer is uninitialized or dangling, evaluating typeid(*p) remains undefined behavior, as the program attempts to read an invalid memory address to access the object’s vtable.
  • Overloading: The unary * operator can be overloaded for user-defined types (e.g., smart pointers, iterators). While it conventionally returns an lvalue reference (T&), the language permits the overload to return by value, which is frequently utilized to return proxy objects in custom iterators.

4. Binary Multiplication Operator

When used as an infix binary operator, * performs arithmetic multiplication on its two operands.
// Syntax
expression1 * expression2
Mechanics:
  • Operand Requirements: Both operands must be of arithmetic types (integral or floating-point) or unscoped enumeration types.
  • Type Conversion: The operands are subject to standard arithmetic conversions and integral promotions before the operation is performed. The type of the result is the common type determined by these conversions.
  • Overflow: If the result exceeds the representable range of the computed type, signed integer overflow results in undefined behavior, whereas unsigned integer overflow wraps around modulo 2n.
  • Overloading: The binary * operator can be overloaded for user-defined types by defining a non-member function T operator*(const L& lhs, const R& rhs) or a member function T operator*(const R& rhs) const.

5. Lambda Capture-by-Copy Specifier

When used in a lambda expression’s capture list preceding the this keyword, * acts as a distinct syntactic modifier indicating capture-by-value semantics for the enclosing object.
// Syntax
[*this]() { /* ... */ }
Mechanics:
  • Capture Semantics: Introduced in C++17, the * token modifies the capture behavior of the enclosing object. Instead of capturing the this pointer by value, *this instructs the compiler to capture the entire enclosing object by value, copying its state directly into the lambda’s generated closure type.
  • Immutability: By default, the copied object within the closure is const. Modifying its members from within the lambda body requires the lambda to be declared mutable.
Master C++ with Deep Grasping Methodology!Learn More