Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Direct-init vs. list-init in array new-expression

Basically, why is this valid:

auto p1 = new int[10]{5};

but this is not:

auto p1 = new int[10](5);

And more generally what are the rules for the new-expression initializer?

I found the following:

— If the new-initializer is omitted, the object is default-initialized (8.5). [ Note: If no initialization is performed, the object has an indeterminate value. — end note ] — Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct- initialization.

So is the second case invalid because smth like T((5)) is invalid (direct initialization from expression (5))? Or what is the reason?

EDIT: well, my suggestion of (()) thing seems dumb because I see no reason why that should only apply to array new-expression.

like image 530
ledonter Avatar asked Apr 05 '18 03:04

ledonter


People also ask

How do you initialize an entire array with a single value?

Initializer List: To initialize an array in C with the same value, the naive way is to provide an initializer list. We use this with small arrays. int num[5] = {1, 1, 1, 1, 1}; This will initialize the num array with value 1 at all index.

How do you initialize all elements of an array to 0 in C++?

The entire array can be initialized to zero very simply. This is shown below. int arr[10] = {0};

What is direct initialization?

Direct Initialization or Assignment Operator (Syntax) This assigns the value of one object to another object both of which are already exists. Copy initialization is used when a new object is created with some existing object. This is used when we want to assign existing object to new object.


1 Answers

The 1st one is valid because of list initialization (since C++11),

new T { arg1, arg2, ... }

and

If T is an aggregate type, aggregate initialization is performed.

int[10] is an array type which belongs to aggregate type, then aggregate initialization is performed,

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.

So auto p1 = new int[10]{5}; will create a pointer to array, whose first element is initialized as 5, the remaining elements are initialized as 0.

The 2nd one is direct initialization, so new int[10](5); means initialize the array int[10] from a single int 5 directly; which is invalid.

In fact, for the array new expression you can't specify a non-empty parenthesized initializer.

If type is an array type, an array of objects is initialized.

  • If initializer is absent, each element is default-initialized
  • If initializer is an empty pair of parentheses, each element is value-initialized.
  • If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since C++11)

So

auto p1 = new int[10];    // valid
auto p2 = new int[10]();  // valid
auto p3 = new int[10]{5}; // valid

auto p4 = new int[10](5); // invalid

EDIT

From the point view of the standard, as you quoted, [expr.new]/18:

A new-expression that creates an object of type T initializes that object as follows:

  • If the new-initializer is omitted, the object is default-initialized ([dcl.init]). [ Note: If no initialization is performed, the object has an indeterminate value. — end note ]

=> Applies for auto p1 = new int[10];, leads to default-initialization.

  • Otherwise, the new-initializer is interpreted according to the initialization rules of [dcl.init] for direct-initialization.

And [dcl.init]/17:

  • (17.1) If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized.

=> Applies for auto p3 = new int[10]{5};, leads to list initialization, details are explained above.

  • (17.4) If the initializer is (), the object is value-initialized.

=> Applies for auto p2 = new int[10]();, leads to value initialization.

  • (17.5) Otherwise, if the destination type is an array, the program is ill-formed.

=> Applies for auto p4 = new int[10](5);.

like image 79
songyuanyao Avatar answered Oct 24 '22 12:10

songyuanyao