Menu

C++ Structs: Group Related Data Into One Type

C++ structs explained - how to bundle related variables into a single type, declare and initialize struct objects, give a struct member functions and constructors, and how struct really differs from class.

This page includes runnable editors - edit, run, and see output instantly.

Why Group Data Together

So far every variable has stood on its own: an int here, a string there. But real programs deal with things made of several pieces - a point has an x and a y, a student has a name, an age, and a GPA. Passing those around as loose, separate variables is error-prone; nothing ties them together, and a function that needs all three must take all three parameters.

A struct fixes this. It defines a new type that bundles related variables - its members - into one unit. Once defined, you treat the whole bundle as a single value you can store, copy, and pass to functions.

You reach each member with the dot operator (s.name, s.age). The semicolon after the closing } of a struct definition is required - leaving it off is one of the most common beginner compile errors in C++.

Initializing a Struct

Assigning each field by hand works, but it's verbose and easy to forget a member. The cleaner option is aggregate initialization: list the values in braces, in the same order the members were declared.

Watch out for the empty default: Point p; (no braces) leaves x and y holding garbage values, because built-in members aren't auto-zeroed. Point p{}; value-initializes them to 0. Prefer the braces. You can also bake in defaults right in the definition, so even Point p; starts clean:

Structs as Function Parameters

A struct is a single value, so a function can take one parameter instead of three. Just remember that passing a struct by value copies every member. For anything bigger than a couple of ints, pass by const reference to skip the copy - the same rule you saw on the references page.

Returning a whole struct from a function is the idiomatic way to hand back several values at once - far cleaner than juggling multiple output references.

Adding Member Functions and Constructors

A struct isn't limited to data. It can hold member functions that operate on its own members, and a constructor that initializes the object the moment it's created. This is where a struct starts to look like a small object with behavior.

Inside a member function the members are accessed by name (width, height) - they refer to this object's copy. Marking area() const tells the compiler the function only reads the object, which lets you call it on const Rectangle values too. Constructors are a topic in their own right, including that : width(w) initializer-list syntax - the constructors page goes deep.

Struct vs. Class: The Real Difference

You may have heard that "structs are for data, classes are for objects." That's a convention, not a language rule. In C++ a struct and a class are almost the same thing - the only built-in difference is the default access level.

struct S {
    int x;        // public by default
};

class C {
    int x;        // private by default
};

Members of a struct are public unless you mark them otherwise; members of a class start out private. That's it - both can have constructors, member functions, inheritance, and everything else. You can even add explicit access specifiers to a struct to hide members:

The practical takeaway: use struct for transparent bundles of data where every field is meant to be touched freely (a Point, a Color, a config record), and reach for class when you want to protect internal state behind a public interface. The compiler treats them the same; the keyword just signals your intent.

Arrays and Vectors of Structs

Because a struct is an ordinary type, you can put many of them in an array or a vector and loop over them like any other value.

Note the nested braces: each {"Keyboard", 49.99} aggregate-initializes one Product, and the outer braces build the vector. Using const Product& in the range-based loop avoids copying each struct on every iteration - drop the & and you'd duplicate every element needlessly.

Next: Enums

Structs let you build a type out of several values bundled together. The next chapter goes the other direction: an enum defines a type that can hold exactly one value out of a small, named set - perfect for things like Color::Red, Direction::North, or a state machine's status. You'll see how enum class gives you readable, type-safe constants that pair naturally with the structs and classes you're now building.

Frequently Asked Questions

What is a struct in C++?

A struct is a user-defined type that groups several related variables (called members) under one name. Instead of juggling separate string name, int age, and double gpa variables, you bundle them into a single Student type and pass that one object around. A struct can also hold member functions and constructors - in modern C++ it's a full-fledged class whose members are public by default.

What is the difference between struct and class in C++?

Technically only the default access level: members of a struct are public unless you say otherwise, while members of a class are private by default. The same is true for inheritance. Everything else - constructors, member functions, methods, inheritance - works identically. By convention, programmers reach for struct for plain data bundles and class for types with invariants and hidden internals.

How do you initialize a struct in C++?

The simplest way is aggregate initialization with braces in member order: Point p{3, 4};. You can also assign each field by hand with the dot operator (p.x = 3;), give members default values in the definition (int x = 0;), or write a constructor so the struct sets itself up. Brace initialization is preferred because it won't silently leave fields uninitialized.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED