zoukankan      html  css  js  c++  java
  • When do we use Initializer List in C++?

      Initializer List is used to initialize data members of a class. The list of members to be initialized is indicated with constructor as a comma separated list followed by a colon.

      Following is an example that uses initializer list to initialize x and y of Point class.

     1 #include<iostream>
     2 using namespace std;
     3 
     4 class Point {
     5 private:
     6     int x;
     7     int y;
     8 public:
     9     Point(int i = 0, int j = 0):x(i), y(j) 
    10     {
    11     } 
    12     /*  The above use of Initializer list is optional as the 
    13     constructor can also be written as:
    14     Point(int i = 0, int j = 0) 
    15     {
    16         x = i;
    17         y = j;
    18     }
    19     */   
    20     
    21     int getX() const 
    22     {
    23         return x;
    24     }
    25     int getY() const 
    26     {
    27         return y;
    28     }
    29 };
    30 
    31 int main() 
    32 {
    33     Point t1(10, 15);
    34 
    35     cout<<"x = "<<t1.getX()<<", ";
    36     cout<<"y = "<<t1.getY();
    37 
    38     return 0;
    39 }
    40 
    41 /* OUTPUT:
    42 x = 10, y = 15
    43 */

      The above code is just an example for syntax of Initializer list. In the above code, x and y can also be easily initialed inside the constructor.

      But there are situations where initialization of data members inside constructor doesn’t work and Initializer List must be used.

      Following are such cases:

      1) For initialization of non-static const data members: const data members must be initialized using Initializer List.

      In the following example, “t” is a const data member of Test class and is initialized using Initializer List.

     1 #include<iostream>
     2 using namespace std;
     3  
     4 class Test 
     5 {
     6     const int t;
     7 public:
     8     Test(int t):t(t) //Initializer list must be used
     9     {
    10     }  
    11     int getT() 
    12     { 
    13         return t; 
    14     }
    15 };
    16  
    17 int main() 
    18 {
    19     Test t1(10);
    20     cout<<t1.getT();
    21     return 0;
    22 }
    23  
    24 /* OUTPUT:
    25    10 
    26 */

      2) For initialization of reference members:Reference members must be initialized using Initializer List.

      In the following example, “t” is a reference member of Test class and is initialized using Initializer List.

     1 // Initialization of reference data members
     2 #include<iostream>
     3 using namespace std;
     4  
     5 class Test 
     6 {
     7     int &t;
     8 public:
     9     Test(int &t):t(t) 
    10     {
    11     }  //Initializer list must be used
    12     int getT() 
    13     { 
    14         return t; 
    15     }
    16 };
    17  
    18 int main() 
    19 {
    20     int x = 20;
    21     Test t1(x);
    22     cout<<t1.getT()<<endl;
    23     x = 30;
    24     cout<<t1.getT()<<endl;
    25     return 0;
    26 }
    27 /* OUTPUT:
    28     20
    29     30
    30  */

      3) For initialization of member objects which do not have default constructor.

      In the following example, an object “a” of class “A” is data member of class “B”, and “A” doesn’t have default constructor. Initializer List must be used to initialize "a".

     1 #include <iostream>
     2 using namespace std;
     3  
     4 class A 
     5 
     6 {
     7     int i;
     8 public:
     9     A(int );
    10 };
    11  
    12 A::A(int arg) 
    13 
    14 {
    15     i = arg;
    16     cout << "A's Constructor called: Value of i: " << i << endl;
    17 }
    18  
    19 // Class B contains object of A
    20 class B 
    21 
    22 {
    23     A a;
    24 public:
    25     B(int );
    26 };
    27  
    28 B::B(int x):a(x) 
    29 
    30 {  
    31 
    32     //Initializer list must be used
    33     cout << "B's Constructor called";
    34 }
    35  
    36 int main() 
    37 
    38 {
    39     B obj(10);
    40     return 0;
    41 }
    42 /* OUTPUT:
    43     A's Constructor called: Value of i: 10
    44     B's Constructor called
    45 */

      If class A had both default and parameterized constructors, then Initializer List is not must if we want to initialize “a” using default constructor, but it is must to initialize “a” using parameterized constructor.

      4) For initialization of base class members : Like point 3, parameterized constructor of base class can only be called using Initializer List.

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class A 
     5 {
     6     int i;
     7 public:
     8     A(int );
     9 };
    10 
    11 A::A(int arg) 
    12 {
    13     i = arg;
    14     cout << "A's Constructor called: Value of i: " << i << endl;
    15 }
    16 
    17 // Class B is derived from A
    18 class B: A 
    19 {
    20 public:
    21     B(int );
    22 };
    23 
    24 B::B(int x):A(x) 
    25 { 
    26     //Initializer list must be used
    27     cout << "B's Constructor called";
    28 }
    29 
    30 int main() 
    31 {
    32     B obj(10);
    33     return 0;
    34 }

      5) When constructor’s parameter name is same as data member
      If constructor’s parameter name is same as data member name then the data member must be initialized either using this pointer or Initializer List. In the following example, both member name and parameter name for A() is “i”.

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class A 
     5 {
     6     int i;
     7 public:
     8     A(int );
     9     int getI() const 
    10     { 
    11         return i; 
    12     }
    13 };
    14 
    15 A::A(int i):i(i) 
    16 { 
    17 }  // Either Initializer list or this pointer must be used
    18 
    19 /* The above constructor can also be written as 
    20 A::A(int i) 
    21 { 
    22     this->i = i;
    23 }
    24 */
    25 
    26 int main() 
    27 {
    28     A a(10);
    29     cout<<a.getI();
    30     return 0;
    31 }
    32 /* OUTPUT:
    33    10
    34 */

      6) For Performance reasons:
      It is better to initialize all class variables in Initializer List instead of assigning values inside body.

      Consider the following example:

     1 // Without Initializer List
     2 class MyClass 
     3 {
     4     Type variable;
     5 public:
     6     MyClass(Type a) 
     7     {  
     8         // Assume that Type is an already
     9         // declared class and it has appropriate 
    10         // constructors and operators
    11         variable = a;
    12     }
    13 };

      Here compiler follows following steps to create an object of type MyClass
      1. Type’s constructor is called first for “a”.
      2. The assignment operator of “Type” is called inside body of MyClass() constructor to assign

       variable = a;
      3. And then finally destructor of “Type” is called for “a” since it goes out of scope.

     1 // With Initializer List
     2 class MyClass 
     3 {
     4     Type variable;
     5 public:
     6     MyClass(Type a):variable(a) 
     7     {   
     8         // Assume that Type is an already
     9         // declared class and it has appropriate
    10         // constructors and operators
    11     }
    12 };

      Now consider the same code with MyClass() constructor with Initializer List With the Initializer List, following steps are followed by compiler:
      1. Copy constructor of “Type” class is called to initialize : variable(a). The arguments in initializer list are used to copy construct “variable” directly.
      2. Destructor of “Type” is called for “a” since it goes out of scope.

      As we can see from this example if we use assignment inside constructor body there are three function calls: constructor + destructor + one addition assignment operator call. And if we use Initializer List there are only two function calls: copy constructor + destructor call. See this post for a running example on this point.

      This assignment penalty will be much more in “real” applications where there will be many such variables. Thanks to ptr for adding this point.

      Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

      转载请注明:http://www.cnblogs.com/iloveyouforever/

      2013-11-26  10:36:51

  • 相关阅读:
    less的一些用法整理
    flex 布局下关于容器内成员 flex属性的理解
    Web开发者需具备的8个好习惯
    GridView分页功能的实现
    程序员长期保持身心健康的几点建议
    程序员必知的10大基础实用算法
    结对编程
    Python_Day_02 str内部方法总结
    Python_Day_01(使用环境为Python3.0+)
    圆形头像制作
  • 原文地址:https://www.cnblogs.com/iloveyouforever/p/3442801.html
Copyright © 2011-2022 走看看