Aggregate Initialization
Initialize arrays and simple structs using brace-enclosed lists without constructors. Concise syntax for multiple members.
Array OR class with: no user constructors, no private/protected members, no base classes, no virtual functions.
Arraysβ
// Full initialization
int arr[5] = {1, 2, 3, 4, 5};
// Partial initialization (rest zeroed)
int arr[5] = {1, 2, 3}; // {1, 2, 3, 0, 0}
// Zero initialization
int arr[5] = {}; // All zeros
Rule: Fewer initializers β remaining elements value-initialized to zero.
Simple Structuresβ
struct Point {
int x;
int y;
};
Point p = {10, 20}; // x=10, y=20 (declaration order)
Order: Members initialized in declaration order.
Nested Aggregatesβ
struct Point { int x, y; };
struct Line { Point start, end; };
Line line = {{0, 0}, {10, 20}}; // β
Clear structure
// Can omit inner braces (less clear)
Line line2 = {0, 0, 10, 20}; // Works but confusing
Best practice: Include inner braces for clarity.
Designated Initializers (C++20)β
Name members explicitly for self-documenting code.
struct Point {
int x;
int y;
int z;
};
Point p = {.x = 10, .y = 20, .z = 30};
// Omit members (zeroed)
Point p2 = {.x = 5, .z = 15}; // y = 0
Benefits: Clear, explicit, can omit members (they're zeroed).
Partial Initializationβ
struct Config {
int timeout;
int retry_count;
bool debug_mode;
int buffer_size;
};
Config cfg = {.timeout = 5000, .debug_mode = true};
// retry_count = 0, buffer_size = 0
Aggregate Requirementsβ
// β
Aggregate
struct Good {
int a;
double b;
};
// β Has constructor
struct Bad1 {
int a;
Bad1(int x) : a(x) {}
};
// β Has private members
struct Bad2 {
private:
int a;
public:
int b;
};
// β Has base class
struct Bad3 : Good {
int c;
};
// β Has virtual function
struct Bad4 {
int a;
virtual void func() {}
};
Restrictions: Keep aggregates simple - just public data members.
Arrays of Aggregatesβ
struct Point { int x, y; };
Point points[3] = {
{0, 0},
{10, 20},
{30, 40}
};
// Partial array initialization
Point points2[5] = {{1, 2}, {3, 4}}; // Last 3 are {0, 0}
Partial Initialization Safetyβ
struct Widget {
int a;
int b;
int c;
};
Widget w = {1, 2}; // {1, 2, 0} - c is zeroed β
Safety: Unspecified members value-initialized (zero for fundamentals).
STL Integrationβ
struct Point { int x, y; };
std::vector<Point> points = {
{0, 0},
{10, 20},
{30, 40}
};
points.emplace_back(Point{50, 60});
Quick Comparisonβ
| Feature | Aggregate | Class with Constructor |
|---|---|---|
| Syntax | {1, 2} | (1, 2) or {1, 2} |
| Boilerplate | None | Constructor code |
| Encapsulation | No | Yes |
| Validation | No | Yes |
| Use case | Plain data | Complex invariants |
// Aggregate (simple)
struct Point { int x, y; };
Point p = {10, 20};
// Class (more control)
class Point {
int x, y;
public:
Point(int x_, int y_) : x(x_), y(y_) {
if (x < 0 || y < 0) throw std::invalid_argument("Negative!");
}
};
Summaryβ
What's an Aggregate:
- Array OR class with all of:
- No user-declared constructors
- No private/protected non-static members
- No base classes
- No virtual functions
Initialization Behavior:
- Braces initialize members in declaration order
- Fewer initializers β remaining members zeroed
- Partial initialization is safe (rest = zero)
- Nested braces for nested aggregates
C++20 Designated Initializers:
- Syntax:
{.x = 10, .y = 20} - Self-documenting (names make intent clear)
- Can omit members (automatically zeroed)
- Must be in declaration order
Best Practices:
- Include inner braces for clarity:
{{0, 0}, {10, 20}} - Use designated initializers for readability
- Order members largeβsmall to minimize padding
- For validation needs: use class with constructor
vs Constructor-Based Classes:
- Aggregates: Less boilerplate, plain data
- Classes: Validation, invariants, encapsulation
- Choose aggregates for simple data structures
- Choose classes when you need control
// Interview answer:
// "Aggregate initialization uses braces to initialize arrays
// and simple structs. Aggregates must have no user constructors,
// all public members, no base classes, no virtual functions.
// Fewer initializers β rest are zeroed. C++20 adds designated
// initializers (.x = 10) for clarity. Use for plain data;
// use constructors when you need validation or invariants."