Aggregates in C++

An aggregate is just what it sounds like: a bunch of things clumped together. This definition includes aggregates of mixed types, like structs and classes. An array is an aggregate of a single type.

(From Bruce Eckel's Thinking in C++)

An aggregate is a class such that

An aggregate gives users direct access to its members and has special initialization syntax.


For example, the following class is an aggregate:

struct Data {
  int ival;
  string s;
};

Aggregate Initialization of Classes and Structures

Initializing aggregates can be error-prone and tedious. C++ aggregate initialization makes it much safer. When you create an object that's an aggregate, all you must do is make an assignment, and the initialization will be taken care of by the compiler. This assignment comes in several flavors, depending on the type of aggregate you're dealing with, but in all cases the elements in the assignment must be surrounded by curly braces.

We can initialize the data members of an aggregate class by providing a braced list of member initializers:

struct Data {
  int ival;
  string s;
};
Data val1 = { 0, "Anna"};

Aggregate Initialization of Arrays

For an array of built-in types initialization is quite simple:

int a[5] = { 1, 2, 3, 4, 5 };

If you try to give more initializers than there are array elements, the compiler gives an error message. But what happens if you give fewer initializers, such as

int b[6] = {0};

Here, the compiler will use the first initializer for the first array element, and then use zero for all the elements without initializers. Notice this initialization behavior doesn't occur if you define an array without a list of initializers. So the above expression is a very succinct way to initialize an array to zero, without using a for loop, and without any possibility of an off-by-one error (Depending on the compiler, it may also be more efficient than the for loop.)

A second shorthand advantage with arrays is automatic counting, where you let the compiler determine the size of the array based on the number of initializers:

int c[] = { 1, 2, 3, 4 };

Initialization Syntax

T object = { arg1, arg2, ... }; // (1)
T object   { arg1, arg2, ... }; // (2) 	(since C++11)
T object = { .des1 = arg1 , .des2 { arg2 } ... }; // (3) 	(since C++20)
T object   { .des1 = arg1 , .des2 { arg2 } ... }; // (4) 	(since C++20)

1) and 2) initialize an aggregate with an ordinary initializer list.

3) and 4) initialize an aggregate with designated initializers (aggregate class only).