Aggregrate:Initialization of structures and arrays in C++

 Aggregrate:Initialization of structures and arrays in C++

先來認識一下C++中的Aggregrate的定義!
8.5.1 Aggregates
1 An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected
non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
2 When an aggregate is initialized the initializer can contain an initializer-clause consisting of a braceenclosed,
comma-separated list of initializer-clauses for the members of the aggregate, written in increasing
subscript or member order. If the aggregate contains subaggregates, this rule applies recursively to the members of the subaggregate. [Example:
struct A {
int x;
struct B {
int i;
int j;
} b;
} a = { 1, { 2, 3 } };
initializes a.x with 1, a.b.i with 2, a.b.j with 3. ]



Initialization of structures and arrays in C++

December 26th, 2003 at 1:46 pm

Suppose you have a large array or structure containing important information, and you want to initialize it to some default values in the beginning of the program. The following is not an optimal solution, it is quite tedious to type (what if the array is 500 elements long ?)

Listing 1:


int arr[5];

arr[0] = 5;
arr[1] = 6;
arr[2] = 2;
arr[3] = 4;
arr[4] = 8;

We can write the same with a lot less typing ! But first, it is worthwhile to understand what an aggregate is.

An aggregate is an array or a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions.

Stated simply: just as its name suggests, an aggregate is a type meant to store data, usually without any other functionality. An aggregate can may be initialized using a brace-enclosed initialization list.

Listing 2:


#include

using namespace std;

int main()
{
// Array initialization. Equivalent to
// Listing 1
//
int arr[5] = {5, 6, 2, 4, 8};

struct Foo
{
int a;
int b;
};

// Structure initialization. Equivalent to:
//
// my_foo.a = 5;
// my_foo.b = 6;
//
Foo my_foo = {5, 6};

struct Bar
{
int a;
int b;
Foo bars_foo;

int bar_arr[2];
};

// Aggregate initializations can be nested !
// The following is equivalent to:
//
// my_bar.a = 5;
// my_bar.b = 6;
// my_bar.bars_foo.a = 6;
// my_bar.bars_foo.b = 7;
// my_bar.bar_arr[0] = 5;
// my_bar.bar_arr[1] = 6;
//
Bar my_bar = {5, 6, {6, 7}, {5, 6}};

return 0;
}

Note that brace-enclosed lists may be used in initialization only, not assignment. That is, only when the structs/arrays are declared. If you have to modify all values in an aggregate some time later, you’ll have to use assignment, as demonstrated in Listing 1.

There is an other aspect to aggregate initialization which can be very helpful sometimes: If some members of an aggregate are initialized, ALL of them are. If you supply only a partial initialization list, the rest will be initialized with zero.

Listing 3:


#include

using namespace std;

int main()
{
// Partial initialization list. arr[0] is
// initialized to 5, arr[1] to 6, and the
// rest to 0
//
int arr[5] = {5, 6};

for (int i = 0; i < 5; ++i)
cout << "arr[" << i << "] = " << arr[i]
<< endl;

struct Foo
{
int a;
unsigned b;
float c;
double d;
};

// Here is a convenient method to initialize
// all members of a structure to 0
//
Foo my_foo = {0};

cout << my_foo.a << endl << my_foo.b << endl
<< my_foo.c << endl << my_foo.d << endl;

return 0;
}

As a final note, remember that only aggregate types may be initialized this way. For arrays this kind of initialization is quite useful (especially the quick all 0 initialization as demonstrated in Listing 3) but for more complex types (structs, classes) it is better to consider constructors.

Update: The method suggested here may be dangerous when some members of the structure are complex classes (for example, the standard string class). These objects may not react well to direct memory initialization. Again, if your structure is complex, it is highly suggested to use a constructor - this way you can control the initialization, and only implement the code once (each instantiation of your structure will implicitly call the constructor)

注意,把struct換成class也是正確的。GCC下驗證通過!
      1 #include <iostream>
      2
      3 using namespace std;
      4
      5 int main()
      6 {
      7     // Partial initialization list. arr[0] is
      8     // initialized to 5, arr[1] to 6, and the
      9     // rest to 0
     10     //
     11     int arr[5] = {5, 6};
     12
     13     for (int i = 0; i < 5; ++i)
     14         cout << "arr[" << i << "] = " << arr[i]
     15                << endl;
     16
     17     class Foo
     18     {
     19 public:
     20         int a;
     21         unsigned b;
     22         float c;
     23         double d;
     24     };
     25
     26     // Here is a convenient method to initialize
     27     // all members of a structure to 0
     28     //
     29     Foo my_foo = {0};
     30
     31     cout << my_foo.a << endl << my_foo.b << endl
     32          << my_foo.c << endl << my_foo.d << endl;
     33
     34     return 0;
     35 }
     36
$ ./a.out
arr[0] = 5
arr[1] = 6
arr[2] = 0
arr[3] = 0
arr[4] = 0
0
0
0
0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章