54

Consider:

struct box
{
    int array[3];
};

int main()
{
    box a = {1};
}

If the above works in C++ then why doesn't the following work?

struct box
{
    int simple_int;
};

int main()
{
    box b = 2;
}

What is the reason?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Naveen
  • 7,944
  • 12
  • 78
  • 165

2 Answers2

90

Properly, the former would use box a = { { 1 } }, so that you have one set of braces for each aggregate. The outer set of braces is for the structure, and the inner set is for the array. However, the language allows you to omit inner braces.

In the latter, there are no inner braces to omit. You are not allowed to omit outer braces; you must have at least one set of braces to distinguish a list of initializers for an aggregate. In a sense, the braces say “Here is a list of things to put inside the aggregate.” When you write box b = 2, the compiler does not know you want to put 2 inside the aggregate. Instead, it looks like you are trying to initialize the b object (rather than part of it) to 2. So the compiler tries to find a constructor or a conversion that changes a 2 into a box. When this fails, you get an error.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 6
    even we are allowed to declare int as: `int i = {10};` – Grijesh Chauhan Jul 29 '13 at 14:04
  • 8
    @GrijeshChauhan: I omitted that because it is not relevant and complicates the discussion. The question is why can we not omit braces, not why can we add them. And it is a special case for scalars that the language specification treats separately, not a part of the rules for aggregates. – Eric Postpischil Jul 29 '13 at 14:06
  • @Eric Yes got! One should keep explanation simple on front of new guy. – Grijesh Chauhan Jul 29 '13 at 14:09
  • @EricPostpischil:By `aggregates` do we mean the variables declared inside the structure? – Naveen Jul 29 '13 at 14:12
  • 3
    @InsaneCoder: Roughly, an aggregate is an object made of other objects. For initialization purposes, an aggregate is an array or class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions. A plain struct containing an array is an aggregate containing an aggregate. – Eric Postpischil Jul 29 '13 at 14:14
  • @EricPostpischil :Does `box a={{10,20,30},50};` means that initialise `box a={10,20,30}`to some array and `50` to an integer.I am asking for this question `http://stackoverflow.com/questions/17926524/strange-behaviour-of-structutes-in-cpart-2#17926660`. – Naveen Jul 29 '13 at 14:41
  • @InsaneCoder no, that means initialize the array inside to `{10,20,30}`, and another element of the struct to `50`. – AJMansfield Jul 29 '13 at 19:39
  • 2
    @AJMansfield: More precisely, it means initialize the **first member** of the struct, which **must be** an array or struct, to `{10, 20, 30}`, and initialize the next member to `50`. It will not go find the array to initialize if it is not the first member. – Eric Postpischil Jul 29 '13 at 19:40
18

It doesn't work because your syntax is wrong. You can add support for b = 2 with an implicit constructor, if that is what you want.

box b = {2}; // correct syntax with no constructor

Or

struct box
{
    // implicit constructor
    box(int i) : i(i) {}
    int i;
};

box b(2);
box c = 2;

Or

struct box
{
    explicit box(int i) : i(i) {}
    int i;
};

box b(2);
box c = 2; // disallowed
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • Neil that is quit similar as `char* s = "A"` and `char* s = {"A"}` both are possible. – Grijesh Chauhan Jul 29 '13 at 14:13
  • 1
    @GrijeshChauhan: Actually `char *s = "A"` is not possible in C++11, anymore (without warning). You have to use `const`. (Well `char*` for string-literal is **deprecated**, to be pedantic) – Nawaz Jul 29 '13 at 14:15
  • 1
    @Nawaz interesting so I have to do either: `const char* s = {"A"}` or `const char* s = "A"` in C++11 **?** – Grijesh Chauhan Jul 29 '13 at 14:16
  • 1
    @GrijeshChauhan: Yes. – Nawaz Jul 29 '13 at 14:17
  • const char* s = {"A"} looks confusing, I would not use it. – Neil Kirk Jul 29 '13 at 14:19
  • @Nawaz Some days back I come to know about: [`int array[] = {};`](http://codepad.org/Q3RNPv32) compiles until you don't use `-pedantic-errors` – Grijesh Chauhan Jul 29 '13 at 14:21
  • VS2012 error C2466: cannot allocate an array of constant size 0 – Neil Kirk Jul 29 '13 at 14:23
  • @GrijeshChauhan: Yes, it is because [zero-sized static arrays](http://stackoverflow.com/questions/9722632/what-happens-if-i-define-a-0-size-array-in-c-c/9722672#9722672) are not allowed in C++. – Nawaz Jul 29 '13 at 14:26