113

If I needed to initialize only a few select values of a C++ struct, would this be correct:

struct foo {
    foo() : a(true), b(true) {}
    bool a;
    bool b;
    bool c;
 } bar;

Am I correct to assume I would end up with one struct item called bar with elements bar.a = true, bar.b = true and an undefined bar.c?

6
  • the bar is just a renaming, if you are using c++ you don't need to do things this way Commented May 28, 2013 at 0:16
  • 14
    @aaronman no, bar is a variable. Commented May 28, 2013 at 0:20
  • 6
    @aaronman I think you're confusing this with typedef struct foo {} bar;. Commented May 28, 2013 at 0:21
  • 1
    So, if bar is the struct, what's foo? Is this the same as defining a foo struct and separately declaring a new variable bar as type foo? Commented Nov 29, 2013 at 4:10
  • 5
    bar is simply a foo object. It is the same as struct foo {//something}; foo bar; Commented Feb 22, 2015 at 21:39

4 Answers 4

320

You don't even need to define a constructor

struct foo {
    bool a = true;
    bool b = true;
    bool c;
 } bar;

To clarify: these are called brace-or-equal-initializers (because you may also use brace initialization instead of equal sign). This is not only for aggregates: you can use this in normal class definitions. This was added in C++11.

Sign up to request clarification or add additional context in comments.

5 Comments

@jamesdlin: Since August 21, 2011, the c++ tag means C++11. People are welcome to say C++98 or C++03 if they want to discuss an old version. And sometime next year, the bare c++ tag will change again to mean C++14.
It's worth noting this immediately makes the type non-POD (verified via std::is_pod<T>::value) and so, in that sense, is equivalent to writing a non-default constructor that sets the same values in an initialiser list.
Actually brace initialization is only allowed when there are no default member initializers in C++11. This limitation is lifted with C++14. ideone uses C++14 but if you use any C++11 compiler that code will fail. en.cppreference.com/w/cpp/language/aggregate_initialization
What if the struct is defined using typedef, like C style? still initializes?
48

Yes. bar.a and bar.b are set to true, but bar.c is undefined. However, certain compilers will set it to false.

See a live example here: struct demo

According to C++ standard Section 8.5.12:

if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value

For primitive built-in data types (bool, char, wchar_t, short, int, long, float, double, long double), only global variables (all static storage variables) get default value of zero if they are not explicitly initialized.

If you don't really want undefined bar.c to start with, you should also initialize it like you did for bar.a and bar.b.

3 Comments

@CaptainObvlious just updated, sorry I was distracted by other stuff and not with computer.
It's not "undefined", it is uninitialized, meaning it has an indeterminate value.
I think OP meant to say that the value is undefined, not the member.
14

You can do it by using a constructor, like this:

struct Date
{
int day;
int month;
int year;

Date()
{
    day=0;
    month=0;
    year=0;
}
};

or like this:

struct Date
{
int day;
int month;
int year;

Date():day(0),
       month(0),
       year(0){}
};

In your case bar.c is undefined,and its value depends on the compiler (while a and b were set to true).

6 Comments

There is no reason to prefer the first form. You should use initialization lists.
@jamesdlin agreed in 99.9% of cases, where the 2nd is vastly preferable for countless reasons. however - just to play devil's advocate! - if rather than ints the members were custom classes that had to meet the definition of trivial (e.g. no non-default constructor), that would be a reason to assign in the body instead of constructing in the init list. however, the number of scenarios in which this is useful are, presumably, a tiny minority, so init lists should definitely be the default recommendation - with the rare exceptions being carefullly qualified and justified, unlike here.
@underscore_d No it wouldn't be such a reason. You can use initialiser lists in all cases except where member variables are interdependent, and that is a violation of 3NF ;-)
@EJP It very much can be a reason; I've needed it several times. I think you're focussing on the parent initialisation, but I'm talking about its members. For member objects whose default ctors are inappropriate & standard layout precludes non-default constructors, one must perform 'initialisation' another way, be it operator= or an init function or whatever. It makes sense to do this 'iniitialisation' in the parent's constructor i.e. assign in its body. operator= here is equivalent to in-body assignment of primitives as in the post. Overthinking or tangential maybe, but true ;-)
@GabrielStaples If you're initializing individual elements of an array, then yes, you would need to do that in a constructor body. Obviously there are some things that must be done in a constructor body. My earlier comment was specifically talking about the specific examples in this answer.
|
5

An explicit default initialization can help:

struct foo {
    bool a {};
    bool b {};
    bool c {};
 } bar;

Behavior bool a {} is same as bool b = bool(); and return false.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.