Consider some type T
(for simplicity, you may assume int
) and some integral constant N
, which we use to define an array like this:
T array[N]{}; // Note the empty braces here!
According tocppreference , value initialization is defined as follows:
This is the initialization performed when an object is constructed with an empty initializer.
But further down it is written:
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.
But then a little bit more down, the following statement appears:
- if T is an array type, each element of the array is value-initialized;
From my understanding, the first and third quoted statements contradict to the second one.
So my two questions are:
Note: I've seen similar questions here but they all differ a bit in the specifics.
Is
T array[N]{}
a value initialization or aggregate initialization?
It is list initialization and part of this initialization process involves aggregate initialization as per dcl.init.list . Additionally, it is also direct list initialization as quoted below.
1 ) List-initialization is initialization of an object or reference from a braced-init-list. Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the initializer-list or designated-initializer-clauses of the designated-initializer-list are called the elements of the initializer list. An initializer list may be empty. List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.
[Note 1: List-initialization can be used
(1.1) as the initializer in a variable definition ([dcl.init])
...
— end note]
The above means that T array[N]{}
is list-initialization.
Now let's move on to how the elements of the array is initialized which is given in dcl.init.list#3 :
3) List-initialization of an object or reference of type T is defined as follows:
3.4) Otherwise, if
T
is an aggregate, aggregate initialization is performed.
And since in our example T array[N]
is an aggregate , the above implies that in our example the whole process of initialization of the array T array[N]
involves aggregate initialization .
Finally, from aggregate initialization given below, we will note that each element is copy-initialized from an empty initializer list:
3) When an aggregate is initialized by an initializer list as specified in [dcl.init.list], the elements of the initializer list are taken as initializers for the elements of the aggregate. The explicitly initialized elements of the aggregate are determined as follows :
3.3) Otherwise, the initializer list must be {}, and there are no explicitly initialized elements.
The above means that there are no explicitly initialized elements in our example so we move onto dcl.init.aggr#5 :
5) For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows :
5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list .
(emphasis mine)
Essentially, this means that each element of type T
of the array will be initialized from an empty initializer list .
Note that this also explains why the following contrived example fails in C++20 :
struct T
{
T() = delete;
};
int main()
{
T array[5]{}; //this fails as a consequence of above explanation
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.