2

I have just tried to use this code and somehow found it not marked error by my compiler.

struct structA{
    int x;
    int y;
};
...
struct structA var;
var={1,2};

This somehow worked well. In my limited knowledge, the {,} clause are only allowed as aggregate initialization. How should I interpret it here?

LTW
  • 29
  • 1

3 Answers3

4

In this case structA is an aggregate, so this form of initialization is allowed.

An aggregate is an array or a class with

  • no user-provided, explicit, or inherited constructors ([class.ctor]),
  • no private or protected non-static data members (Clause [class.access]),
  • no virtual functions, and no virtual, private, or protected base classes ([class.mi]).

So this will be allowed:

struct structA var = {1,2};

But what you actually have is assignment which is also allowed (from C++11) because you are using an initializer list as rhs.

If the right operand is a braced-init-list

  • if the expression E1 has class type, the syntax E1 = {args...} generates a call to the assignment operator with the braced-init-list as the argument, which then selects the appropriate assignment operator following the rules of overload resolution.
P.W
  • 26,289
  • 6
  • 39
  • 76
0

Such initialization is allowed for aggregate only, that includes POD class.

structA is POD (Plain Old Data). Therefore it won't produce error.

If you change your structA to :

struct structA{
    int x;
    int y;
    structA(int, int){} //user-defined constructor
 };

It will produce error. See this What is assignment via curly braces called? and can it be controlled? for more information

gameon67
  • 3,981
  • 5
  • 35
  • 61
0

See the section "Builtin Direct Assignment" on this page:

https://en.cppreference.com/w/cpp/language/operator_assignment

Builtin direct assignment
The direct assignment expressions have the form

lhs = rhs   (1) 
lhs = {}    (2) (since C++11)
lhs = { rhs }   (3) (since C++11)
For the built-in operator, lhs may have any non-const scalar type and rhs must be implicitly convertible to the type of lhs.

The direct assignment operator expects a modifiable lvalue as its left operand and an rvalue expression or a braced-init-list (since C++11) as its right operand, and returns an lvalue identifying the left operand after modification.

For non-class types, the right operand is first implicitly converted to the cv-unqualified type of the left operand, and then its value is copied into the object identified by left operand.

When the left operand has reference type, the assignment operator modifies the referred-to object.

If the left and the right operands identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same)

If the right operand is a braced-init-list

if the expression E1 has scalar type,
the expression E1 = {} is equivalent to E1 = T{}, where T is the type of E1.
the expression E1 = {E2} is equivalent to E1 = T{E2}, where T is the type of E1.

if the expression E1 has class type, the syntax E1 = {args...} generates a call to the assignment operator with the braced-init-list as the argument, which then selects the appropriate assignment operator following the rules of overload resolution. Note that, if a non-template assignment operator from some non-class type is available, it is preferred over the copy/move assignment in E1 = {} because {} to non-class is an identity conversion, which outranks the user-defined conversion from {} to a class type.

sanjivgupta
  • 396
  • 3
  • 12
  • It's better to at least quote some of the relevant text, or add your own description. Even though we hope cppreference.com won't disappear, addresses could always change and content be reorganized. – Useless Aug 20 '21 at 16:46