Designated initializers are a feature in C++ that allows developers to initialize specific members of an aggregate type by explicitly naming the members. This pattern originated in the C language as part of the C99 standard, where it was introduced to provide more explicit and self-documenting initialization of structures. The feature was later adopted into C++ with the C++20 standard. Prior to designated initializers, C++ developers had to rely on positional initialization (which can be error-prone when structures have many members) or constructor-based initialization approaches.
Designated initializers solve numerous problems in modern C++ development. They improve code readability by making it immediately clear which members are being initialized, rather than requiring developers to cross-reference the struct definition to understand the initialization order. They enhance maintainability by making code more resilient to changes in struct member ordering. They enable partial initialization where only a subset of members need non-default values. Additionally, they reduce the need for numerous constructor overloads or builder patterns in cases where many different combinations of initial values might be needed.
struct Point {
int x = 0;
int y = 0;
};
// Using designated initializers
Point p1{.x = 10, .y = 20};
// Only initializing one member, the other keeps its default
Point p2{.x = 5}; // y remains 0struct Rectangle {
Point topLeft;
Point bottomRight;
};
// Nested designated initializers
Rectangle rect{
.topLeft = {.x = 10, .y = 10},
.bottomRight = {.x = 20, .y = 20}
};struct Configuration {
std::string hostname = "localhost";
int port = 8080;
bool useSSL = false;
};
// Only override specific values
Configuration config{
.port = 443,
.useSSL = true
}; // hostname remains "localhost"- Designated initializers must appear in the same order as the members are declared in the class/struct.
- You cannot mix designated and non-designated initializers in the same initialization.
- They only work with aggregate types (structures, classes without user-provided constructors, etc.).
- C++ designated initializers do not allow for out-of-order initialization like C99 does.
// Positional initialization - less clear, depends on order
Point p{10, 20};
// With designated initializers - explicit about which field is which
Point p{.x = 10, .y = 20};// Using constructors requires writing them
class Config {
public:
Config(std::string host, int p) : hostname(host), port(p) {}
std::string hostname;
int port;
};
// With designated initializers, no constructor needed
struct Config {
std::string hostname;
int port;
};
Config c{.hostname = "example.com", .port = 8080};- Use designated initializers for structures with multiple members to improve readability.
- Provide default values in the structure definition for members that have sensible defaults.
- Consider designated initializers as an alternative to multiple constructors for configuration-like structures.
- Document the purpose of each member in the structure itself to make initialization even more clear.
- "Effective Modern C++" by Scott Meyers mentions modern initialization techniques.
- "C++20: The Complete Guide" by Nicolai M. Josuttis covers designated initializers in detail.
- "Professional C++" by Marc Gregoire includes sections on aggregate initialization and designated initializers.
- The C++20 standard itself documents the feature (ISO/IEC 14882:2020).
This code is provided under the MIT License. Feel free to use, modify, and distribute as needed.
Contributions are welcome! Please feel free to submit a Pull Request.