A struct (or structure) is a program-defined datatype which can hold different datatype values called as data members. This is also an aggregate datatype.
A simple example of a struct can be,
struct Pixel{ int x{}; int y{};}; Pixel a{};
Pixel is a struct containing x and y data members, which define the pixel position. Pixel is value-initialized so x and y values are most probably zero.
Accessing data members
We can access data members of a struct using dot (.) operator also called member selection operator. For example,
A struct can be initialized by providing an initializer list which is a braced list comma separated values. As struct is an aggregate, this is called aggregate initialization.
The data members are initialized from the values in the list in the order as they are defined in struct. For example,
Pixel a{1, 9};
If the initializer list is missing some values then data members either initialized with the defined default value or value-initialized (with 0 mostly). For example,
Pixel a{1};std::cout << a.x << "\n"; // prints 1std::cout << a.y << "\n"; // prints 0
Tip
Which means that we can initialize a struct simply as
Pixel a{};
It value-initializes all the data members.
Note
Consider the following case:
struct Pixel{ int x: // default initialize (bad. any garbage value) int y{}; // value initialize (default 0)}
If we do Pixel a;, a.x is default initialized with a garbage value and a.y is value initialized. But if we do Pixel a{};, both are value initialized. So, we should follow latter approach.
Designated initializers
In the initializers list, it is also possible to provide data members name with the initialization value (using list or copy initialization). However, the order of the data members should be followed. For example,
Advantage with this method is that it makes it explicit which data member is initialized with what. Also, if we add any more data members in between, the initialization would not break as shown below,
struct Pixel{ int x; int test; int y;};Pixel a{1, 2};
We would want a.y to be 2 but it gets value initialized as 2 is initialized to test.
The problem with this approach is that it makes the initialization cluttered and hard to read.
Assignment with initializers list
If we have to change the value of data members of struct, we can individually do that. But if there is a requirement of changing whole, we can use initializers list to do so as shown below,
Pixel a{1, 2};a = {2, 3};
Assignment with designated initializers
We can use designated initializers for assignment as shown below,