Language[lang]

Struct in C++: declare, initialize and use one

Section
Language [lang]
Standard
C++17
Compilers
MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2, Clang 23.1 (libc++)
Published
Length
6 min read
In this answer7 clauses
  1. 1How do you initialize a struct in C++?
  2. 2How do you access the members of a struct?
  3. 3How do you pass a struct to a function, or return one?
  4. 4Can a struct have functions and constructors?
  5. 5Struct vs class in C++: what is the difference?
  6. 6How do you keep structs in a vector?
  7. 7A struct checklist

Abstract

A struct in C++ is a type that groups several named values, its members, under one name: declare struct Point { int x; int y; };, create one with Point p{3, 4}; and read a member with p.x, or with ptr->x when ptr points to p. Give members default values and create structs with braces, so nothing is left unset. A struct can have everything a class has; its members and base classes are public by default, where a class makes them private.

Three hatched boxes, one wide and two narrow, lie loose and tilted on the left. An arrow points right to the same three boxes held together inside one larger blue outlined box.
Figure 1 — Separate values, grouped into one: that is what a struct is.

A struct in C++ is a type you define that groups several values, its members, under one name: struct Point { int x; int y; };. You create one with Point p{3, 4}; and read a member with a dot, p.x. A struct can do everything a class can; its members are public unless you say otherwise.

A whole program that makes a Point, prints it and changes one member:

[Example 1:
#include <iostream>

struct Point {
    int x;
    int y;
};

int main() {
    Point p{3, 4};

    std::cout << p.x << ", " << p.y << '\n';  // prints 3, 4

    p.x = 10;
    std::cout << p.x << ", " << p.y << '\n';  // prints 10, 4
}

— end example]

It printed:

[Example 2:
3, 4
10, 4

— end example]

The samples are C++17, built with MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2 and Clang 23.1 (libc++), and all four printed the same. Two features below need C++20, and each says so; Since When lists the first compiler releases for each standard’s features.

How do you initialize a struct in C++?

Put the values in braces, in the order the members are declared. A member you leave out takes the default value written in the struct, and a member with no default is set as if from empty braces, which makes an int 0 (aggregate initialization on cppreference). This Player gives score a default:

[Example 3:
struct Player {
    std::string name;
    int score = 0;  // a default value
};
// ...
Player ada{"Ada", 90};  // in the order the members are declared
Player guest;           // name is empty, score takes its default
Point origin{};         // empty braces: x and y are 0

std::cout << ada.name << ' ' << ada.score << '\n';  // Ada 90
std::cout << '[' << guest.name << "] " << guest.score
          << '\n';                                  // [] 0
std::cout << origin.x << ", " << origin.y << '\n';  // 0, 0

— end example]

It printed:

[Example 4:
Ada 90
[] 0
0, 0

— end example]

guest had no braces and still came out set: a std::string starts empty, and score took its default. An int with no default gets no such help.

Since C++20 you can also name each member as you set it, with a designated initializer; the names must come in the order the members are declared (the first compilers with designated initializers):

[Example 5:
Point p{.x = 3, .y = 4};  // C++20: designated initializers

std::cout << p.x << ", " << p.y << '\n';  // prints 3, 4

— end example]

Built as C++20, all four printed 3, 4. Built as C++17, MSVC refused the line with error C7555, which asks for /std:c++20, while GCC and Clang accepted it as an extension, without a warning at -Wall -Wextra.

How do you access the members of a struct?

Use a dot on the struct itself, ada.score, and an arrow through a pointer to it, p->score.

A box labelled Player ada has two compartments: name holding Ada, score holding 90. A pointer cell p points to the whole box. Arrows from ada.score above and p arrow score below both reach the score compartment.
Figure 2 — A struct is one value made of named members: reach one with a dot, or with an arrow through a pointer.
[Example 6:
Player ada{"Ada", 90};
ada.score = 95;        // a dot on the struct itself

Player* p = &ada;      // a pointer to ada
p->score += 5;         // an arrow through the pointer

std::cout << ada.name << ' ' << ada.score << '\n';  // Ada 100
std::cout << p->name << ' ' << (*p).score << '\n';  // Ada 100

— end example]

Both lines printed Ada 100, because p holds the address of ada itself, not a copy. (*p).score, which follows the pointer and then uses a dot, reached the same member as p->score: the arrow is the short way to write it.

How do you pass a struct to a function, or return one?

Take it as const Player&, a reference to the caller’s struct that the function can read but not change, so nothing is copied. Return a struct to hand back several values at once:

[Example 7:
void print(const Player& player) {  // reads it, copies nothing
    std::cout << player.name << ": " << player.score << '\n';
}

struct MinMax {
    int min;
    int max;
};

MinMax min_max(const std::vector<int>& scores) {
    MinMax result{scores[0], scores[0]};
    for (int s : scores) {
        if (s < result.min) result.min = s;
        if (s > result.max) result.max = s;
    }
    return result;  // two values handed back as one
}
// ...
print(Player{"Ada", 90});  // prints Ada: 90

std::vector<int> scores{72, 90, 85};
auto [low, high] = min_max(scores);  // C++17: structured binding

std::cout << low << ' ' << high << '\n';  // prints 72 90

— end example]

It printed Ada: 90, then 72 90. auto [low, high] is a structured binding, new in C++17: it takes one name per member of the returned struct, so low got min and high got max.

Can a struct have functions and constructors?

Yes: a struct can have member functions, constructors and everything else a class can have. This Player has a constructor and two member functions:

[Example 8:
struct Player {
    std::string name;
    int score;

    Player(std::string n, int s) : name(std::move(n)), score(s) {}

    void add(int points) { score += points; }

    void print() const {
        std::cout << name << ": " << score << '\n';
    }
};
// ...
Player ada("Ada", 90);  // calls the constructor
ada.add(10);
ada.print();            // prints Ada: 100

— end example]

It printed Ada: 100. A struct with a constructor is created with that constructor’s arguments, as ada is here. It is no longer an aggregate, the plain kind of struct that braces fill member by member. The C++ constructor answer covers default, copy and move constructors.

Struct vs class in C++: what is the difference?

Only the defaults. A struct’s members are public unless you write private:, and a class’s are private unless you write public: (class declaration on cppreference). The same holds for base classes, the types a struct or class inherits from: public by default in a struct, private in a class (derived classes on cppreference).

The same two members in a class cannot be reached from main:

[Example 9:
class Point {
    int x;  // private: a class's default
    int y;
};

int main() {
    Point p{};
    p.x = 3;  // error: x is private
}

— end example]

Clang stopped at the assignment, and GCC and MSVC refused it too:

[Example 10:
error: 'x' is a private member of 'Point'

— end example]

Question struct class
Members and base classes, by default public private
Use it when the members can each hold any value the type has a rule its members must keep

The second row is the convention of the C++ Core Guidelines (C.2); they also ask for class whenever any member is not public (C.8).

How do you keep structs in a vector?

Make a std::vector<Player>, add each player with push_back({"Ada", 90}), and loop over them with a range-for that takes each one as const Player&:

[Example 11:
std::vector<Player> players;
players.push_back({"Ada", 90});
players.push_back({"Grace", 85});
players.push_back({"Linus"});  // score takes its default, 0

for (const Player& p : players) {
    std::cout << p.name << ": " << p.score << '\n';
}

— end example]

It printed Ada: 90, Grace: 85 and Linus: 0. How a vector stores its elements and grows is in the std::vector answer.

A struct checklist

  • Give each member a default value, as int score = 0; does.
  • Create structs with braces: Player ada{"Ada", 90};, or Point p{}; for all zeros.
  • Pass a struct to a function as const Player&; return one to hand back several values.
  • Write struct for plain data anyone may read and change, class when the type protects its data.
  • Expect == on a struct to compile only once there is an operator== for the type (the FAQ shows the C++20 line).

The Language section has the other answers on the core language.

Questions

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

Only the default access. A struct’s members and base classes are public unless you write private: or protected:, and a class’s are private unless you write public:. Apart from that the two keywords declare the same kind of type, so a struct can have constructors, member functions and private members too.

Can a struct have a constructor in C++?

Yes. A struct can have constructors and member functions, like a class. Once it has a constructor, you create it with that constructor’s arguments, as in Player ada(“Ada”, 90);, and braces no longer fill it member by member.

Can you compare two structs with == in C++?

Not by default: C++ does not write one unless asked, and a == b compiles only once there is an operator== for the type. The line bool operator==(const Point&) const = default; inside the struct has the compiler compare the members in the order they are declared, and != works from it too. That line needs C++20 (-std=c++20, or /std:c++20 on MSVC); before C++20, write the operator yourself, comparing member by member.

How do you initialize a struct to zero?

Write empty braces: for struct Point { int x; int y; };, Point origin{}; sets x and y to 0. A member that has a default value written in the struct takes that value instead. Without the braces, a local Point origin; leaves x and y, its int members, unset.

What is the size of a struct in C++?

At least the sum of its members’ sizes, and often more, because the compiler may add padding, unused bytes that let each member start where its type needs. For struct Mixed { char c; int i; };, sizeof printed 8 on MSVC, GCC and Clang: 5 bytes of members and 3 of padding. Ask sizeof rather than adding the members up.

Can a struct inherit from another struct?

Yes. A struct can inherit from a struct or a class exactly as a class can. The one difference is the default: with no access word before the base’s name, inheritance is public when the type being declared is a struct and private when it is a class, whatever keyword the base was declared with.

Read next

  1. C++ array: declare, initialize and get the lengthLanguage · Miriam Castellanos · written for C++17
  2. C++ class: how to define one and create objectsLanguage · Miriam Castellanos · written for C++17
  3. Polymorphism in C++: one call, many behaviorsLanguage · Miriam Castellanos · written for C++17