Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Initializing Struct Members
Initialize all struct members at once using brace initialization syntax.
Initializing structs
The previous lesson showed how to define structs and access their members individually. But assigning each member one by one is tedious:
Book novel{};
novel.title = "1984";
novel.author = "George Orwell";
novel.pages = 328;
novel.year = 1949;
C++ provides cleaner ways to initialize all members at once.
Uninitialized members are dangerous
Without initialization, struct members contain garbage values:
#include <iostream>
struct Dimensions
{
int width; // no initializer
int height; // no initializer
};
int main()
{
Dimensions box; // no initializer here either
std::cout << box.width << '\n'; // undefined behavior!
return 0;
}
This program might print anything - or crash. Always initialize your structs.
Aggregate initialization with braces
Structs are aggregates - types containing multiple members. C++ provides aggregate initialization using a braced list:
struct Book
{
std::string title{};
std::string author{};
int pages{};
int year{};
};
int main()
{
Book novel{ "1984", "George Orwell", 328, 1949 };
return 0;
}
Values are assigned to members in declaration order:
titlegets"1984"authorgets"George Orwell"pagesgets328yeargets1949
This is called memberwise initialization.
There's also a copy-list form with =:
Book classic = { "Pride and Prejudice", "Jane Austen", 279, 1813 };
Both work, but prefer the direct brace form without =.
Use direct brace initialization for aggregates: `Book novel{ "1984", "George Orwell", 328, 1949 };`
Providing fewer values than members
You don't need to initialize every member explicitly:
struct Book
{
std::string title{};
std::string author{};
int pages{};
int year{};
};
int main()
{
Book partial{ "Dune", "Frank Herbert" }; // pages and year not specified
return 0;
}
Members without explicit values are initialized based on:
- Their default member initializer (if present)
- Value initialization (typically zero or empty) otherwise
So partial.pages becomes 0 and partial.year becomes 0.
Empty braces value-initialize everything
An empty initializer list value-initializes all members:
Book blank{}; // title="", author="", pages=0, year=0
This is the safest way to ensure no garbage values. Always use at least empty braces.
Default member initializers
You can specify default values directly in the struct definition:
struct NetworkConfig
{
std::string host{ "localhost" };
int port{ 8080 };
int timeout{ 30 };
bool secure{ false };
};
int main()
{
NetworkConfig local{}; // uses all defaults
NetworkConfig custom{ "api.example.com", 443, 60, true }; // overrides all
NetworkConfig partial{ "db.local" }; // host overridden, others use defaults
return 0;
}
When you provide values during initialization, they override the defaults. When you don't, the defaults apply.
Designated initializers (C++20)
Standard aggregate initialization relies on order. Add a member in the middle, and existing initializers shift:
struct Viewport
{
int x{};
int y{};
int width{};
int height{};
};
Viewport window{ 0, 0, 800, 600 }; // clear what each value means?
Designated initializers name each member explicitly:
Viewport window{ .x = 0, .y = 0, .width = 800, .height = 600 };
Or with brace initialization:
Viewport window{ .x{ 0 }, .y{ 0 }, .width{ 800 }, .height{ 600 } };
Key rules:
- Members must appear in declaration order
- Unmentioned members are value-initialized
// Skip x and y, they'll be value-initialized to 0
Viewport centered{ .width{ 1024 }, .height{ 768 } };
Designated initializers add clarity but also verbosity. Use them when order isn't obvious or when skipping members.
Add new members at the end of struct definitions to avoid breaking existing initializations.
Const and constexpr structs
Struct variables can be const:
struct Point
{
double x{};
double y{};
};
int main()
{
const Point origin{ 0.0, 0.0 };
// origin.x = 1.0; // Error: can't modify const
constexpr Point unit{ 1.0, 1.0 }; // compile-time constant
return 0;
}
Const structs must be initialized and cannot be modified afterward.
Assignment with initializer lists
After creation, you can reassign all members at once:
struct Color
{
int r{};
int g{};
int b{};
};
int main()
{
Color background{ 255, 255, 255 }; // white
background = { 0, 0, 0 }; // now black
return 0;
}
This performs memberwise assignment - each member is assigned the corresponding value.
To keep some members unchanged, you must provide their current values:
background = { background.r, 128, background.b }; // only change green
With designated initializers (C++20):
background = { .r = background.r, .g = 128, .b = background.b };
Undesignated members get value-initialized (reset to zero), so always include members you want to preserve.
Copying structs
A struct can be initialized from another struct of the same type:
#include <iostream>
struct Rectangle
{
double width{};
double height{};
};
int main()
{
Rectangle original{ 10.0, 5.0 };
Rectangle copy1 = original; // copy initialization
Rectangle copy2(original); // direct initialization
Rectangle copy3{ original }; // direct-list initialization
std::cout << copy1.width << " x " << copy1.height << '\n';
return 0;
}
All three create independent copies with the same member values. The original and copies are separate objects.
Printing structs with operator<<
Define operator<< to print your structs conveniently:
#include <iostream>
#include <string>
struct Book
{
std::string title{};
std::string author{};
int pages{};
int year{};
};
std::ostream& operator<<(std::ostream& out, const Book& b)
{
out << b.title << " by " << b.author << " (" << b.year << ", " << b.pages << " pages)";
return out;
}
int main()
{
Book novel{ "The Hobbit", "J.R.R. Tolkien", 310, 1937 };
std::cout << novel << '\n';
return 0;
}
Output:
The Hobbit by J.R.R. Tolkien (1937, 310 pages)
The function takes the stream by reference, outputs formatted data, and returns the stream for chaining.
Summary
- Aggregate initialization uses braced lists to initialize all members at once
- Memberwise initialization assigns values in declaration order
- Fewer values than members means remaining members use defaults or value initialization
- Empty braces
{}value-initialize all members safely - Default member initializers provide fallback values in the struct definition
- Designated initializers (C++20) name members explicitly for clarity
- Const structs must be initialized and cannot be modified
- Assignment with initializer lists replaces all member values at once
- Copying structs creates independent objects with identical member values
- Overloading operator<< enables convenient printing with
std::cout
Initializing Struct Members - Quiz
Test your understanding of the lesson.
Practice Exercises
Struct Aggregate Initialization
Practice creating and initializing structs using aggregate initialization. Learn about designated initializers and default member values.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!