C++ Aggregate Initialization | Braces for Structs and Arrays
이 글의 핵심
Aggregate types are structs/arrays you can brace-initialize member-by-member. Pair this with designated initializers (C++20), value vs default init, and care with non-POD members like std::string.
What is aggregate initialization?
An aggregate is a struct or array (under the standard rules) without user-provided constructors, private/protected non-static data members, virtual functions, etc. You initialize it with a brace list.
struct Point {
int x;
int y;
};
Point p = {10, 20}; // aggregate initialization
Why it matters:
- Brevity: no ctor boilerplate for plain data
- Safety: explicit member values
- Readability: definition and initialization stay aligned
// Verbose ctor style
struct Point {
int x, y;
Point(int x_, int y_) : x(x_), y(y_) {}
};
Point p(10, 20);
// Aggregate style
struct Point { int x, y; };
Point p = {10, 20};
Aggregate rules (C++17/C++20 oriented)
Roughly, all of the following must hold:
- Array or class type (struct/class/union)
- No user-provided constructors (compiler-generated defaults OK)
- No private/protected non-static data members
- No virtual functions
- No virtual/private/protected base classes (C++17+: public inheritance allowed)
struct Aggregate1 {
int x;
double y;
};
struct Aggregate2 : Aggregate1 {
int z; // C++17: public base OK
};
struct NonAggregate1 {
NonAggregate1() = default; // if user-defined ctor—breaks aggregate in many cases
// (actual rules depend on edition—check `is_aggregate`)
};
Check at compile time:
#include <type_traits>
struct Point { int x, y; };
static_assert(std::is_aggregate_v<Point>);
Examples
Structs
struct Person {
std::string name;
int age;
double height;
};
Person p1 = {"Alice", 30, 165.5};
Person p2{"Bob", 25, 175.0};
Person p3 = {"Charlie", 35}; // height value-initialized
Person p4 = {"David"}; // age, height value-initialized
Arrays
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {1, 2}; // rest zero
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
Nested structs
struct Address {
std::string city;
int zipCode;
};
struct Person {
std::string name;
Address address;
};
Person p = {
"Alice",
{"Seoul", 12345}
};
C++20 designated initializers
struct Config {
int width = 800;
int height = 600;
bool fullscreen = false;
};
Config cfg = {
.width = 1920,
.height = 1080,
.fullscreen = true
};
Compared to other init forms
| Syntax | Meaning (aggregate S) |
|---|---|
S a; | Default initialization — locals may be indeterminate |
S a{}; | Value initialization — zeros / empty / defaults |
S a = {1, 2}; | Aggregate init (copy-list form) |
S a{1, 2}; | Aggregate + list init |
Non-aggregates go through constructors for S a{...}.
C++20 designated initializers (detail)
Use .member = value in declaration order; skipped members are value-initialized. Out-of-order designation is ill-formed in C++ (unlike some C rules).
Pros: field names in code; fewer order mistakes.
Caveats: refactoring member order breaks call sites; non-aggregates need ctors instead.
Default member values
Omitted trailing members use default member initializers if present, otherwise value initialization.
struct Config {
int width = 800;
int height = 600;
bool fullscreen; // no default
};
Config c1 = {}; // all filled per rules
Config c2 = {1920}; // width only
Common issues
Order (designated)
Point p = {.x = 10, .y = 20}; // OK
// Point q = {.y = 20, .x = 10}; // error in C++20
Types with constructors
Non-aggregates cannot use pure {...} aggregate init—use ctors.
Inheritance
struct Base { int x; };
struct Derived : Base { int y; };
Derived d = {{10}, 20};
Array bounds
int arr1[5] = {1, 2, 3};
int arr2[] = {1, 2, 3};
// int arr3[2] = {1, 2, 3}; // error
FAQ
Q1: Aggregate conditions?
A: Public members, no user-provided ctor (per rules), no virtuals—see std::is_aggregate.
Q2: Partial omission?
A: Yes; remaining members use defaults or value init.
Q3: Order?
A: Declaration order; designated init must follow declaration order in C++.
Q4: C++20 changes?
A: Designated initializers for aggregates.
Related: List initialization, Value initialization, Default initialization.
One line: Aggregate initialization fills struct/array members directly with braces—simple and explicit.
Related posts
- C++ List initialization
- C++ Value initialization
- C++ Designated initializers
- C++ Default initialization
Keywords
C++, aggregate initialization, struct, array, designated initializers.
More links
- C++ Aggregate types
- C++ struct vs class
- C++ array vs vector