程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 類的初始化列表如何提高程序效率

類的初始化列表如何提高程序效率

編輯:C++入門知識

1:類的初始化列表是怎麼提高效率的?
2:類的初始化列表是按照列表中出現的順序來初始化的嗎?
看下面的兩個程序代碼:
程序一

 

[cpp] 
class A 

public: 
  A(int t=0) 
  { 
      cout<<"construct A"<<endl; 
  } 
  A(const A &) 
  { 
      cout<<"copy A"<<endl; 
  } 
  A & operator =(const A &) 
  { 
      cout<<"equal"<<endl; 
      return *this; 
  } 
  ~A() 
  { 
      cout<<"destory A"<<endl; 
  } 
}; 
class B 

public: 
    A a; 
    B() 
    { 
        a=0; 
    } 
}; 
int main() 

    B b; 
    return 0; 

class A
{
public:
  A(int t=0)
  {
   cout<<"construct A"<<endl;
  }
  A(const A &)
  {
   cout<<"copy A"<<endl;
  }
  A & operator =(const A &)
  {
   cout<<"equal"<<endl;
   return *this;
  }
  ~A()
  {
   cout<<"destory A"<<endl;
  }
};
class B
{
public:
 A a;
 B()
 {
  a=0;
 }
};
int main()
{
    B b;
 return 0;
}程序二
[cpp] 
class A 

public: 
  A(int t=0) 
  { 
      cout<<"construct A"<<endl; 
  } 
  ~A() 
  { 
      cout<<"destory A"<<endl; 
  } 
}; 
class B 

public: 
    A a; 
    B():a(0) 
    { 
    } 
}; 
int main() 

    B b; 
    return 0; 

class A
{
public:
  A(int t=0)
  {
   cout<<"construct A"<<endl;
  }
  ~A()
  {
   cout<<"destory A"<<endl;
  }
};
class B
{
public:
 A a;
 B():a(0)
 {
 }
};
int main()
{
    B b;
 return 0;
}程序一與程序二的運行結果是不同的,程序一中多了一次構造與析構函數,賦值函數的調用,這就是初始化列表提高效率的地方
程序一在編譯器器層被轉化成了
[cpp]
B() 

    //以下代碼不可實際運行,只是說明問題  
    a.A::A(0);//調用A的構造函數  
    A tmp(0);//產生一個臨時的對象  
    a=tmp;//通過賦值運算符將臨時對象賦給a  
    tmp.A::~A;//釋放臨時對象的空間  

 B()
 {
  //以下代碼不可實際運行,只是說明問題
  a.A::A(0);//調用A的構造函數
  A tmp(0);//產生一個臨時的對象
  a=tmp;//通過賦值運算符將臨時對象賦給a
  tmp.A::~A;//釋放臨時對象的空間
 }下面是相應的匯編代碼:可以發現和上面的過程分析是一樣的,有興趣可以自已研究下
[cpp]
00401227   call        @ILT+15(A::A) (00401014) 
0040122C   mov         dword ptr [ebp-4],0 
29:       { 
30:           a=0; 
00401233   push        0 
00401235   lea         ecx,[ebp-14h] 
00401238   call        @ILT+15(A::A) (00401014) 
0040123D   mov         byte ptr [ebp-4],1 
00401241   lea         eax,[ebp-14h] 
00401244   push        eax 
00401245   mov         ecx,dword ptr [ebp-10h] 
00401248   call        @ILT+0(A::operator=) (00401005) 
0040124D   mov         byte ptr [ebp-4],0 
00401251   lea         ecx,[ebp-14h] 
00401254   call        @ILT+120(A::~A) (0040107d) 
31:       } 

00401227   call        @ILT+15(A::A) (00401014)
0040122C   mov         dword ptr [ebp-4],0
29:       {
30:           a=0;
00401233   push        0
00401235   lea         ecx,[ebp-14h]
00401238   call        @ILT+15(A::A) (00401014)
0040123D   mov         byte ptr [ebp-4],1
00401241   lea         eax,[ebp-14h]
00401244   push        eax
00401245   mov         ecx,dword ptr [ebp-10h]
00401248   call        @ILT+0(A::operator=) (00401005)
0040124D   mov         byte ptr [ebp-4],0
00401251   lea         ecx,[ebp-14h]
00401254   call        @ILT+120(A::~A) (0040107d)
31:       }程序二在底層被轉化成了[cpp] view plaincopyprint?
B():a(0) 

    a.A::A(0); 

 B():a(0)
 {
  a.A::A(0);
 }可以發現通過初始化列表在申請了對象a的空間後直接調用初始化列表中指定的構造函數來構造成員對象,因此少了很多中間步驟,因此提高了程序的效率:)
這是程序二對應的匯編代碼(看看就知道了吧:)):
[cpp] 
0040120A   mov         dword ptr [ebp-4],ecx 
0040120D   push        0 
0040120F   mov         ecx,dword ptr [ebp-4] 
00401212   call        @ILT+10(A::A) (0040100f) 

0040120A   mov         dword ptr [ebp-4],ecx
0040120D   push        0
0040120F   mov         ecx,dword ptr [ebp-4]
00401212   call        @ILT+10(A::A) (0040100f)到這了,初始化列表確實能夠提高程序的效率,不是嗎:),初始化列表就是指明了應該調用成員對象的哪個構造函數
對於第二個問題並不是按初始化列表來構造成員的,就不做實驗了,有興趣的可一塊討論,構造函數初始化的順序是按這個順序,先根據基類的聲明順序,調用基類的構造函數,初始化基類,再按照類裡面成員對象的聲明順序調用成員對象的構造函數對成員對象進行初始化:)
以下幾種情況一定要用到初始化列表
1:當初始化一個引用成員對象時
2:當初始化一個const成員對象時(1、2兩種情況可以想想為什麼?原理是一樣的,注意強調的是對象)
3:當調用一個基類的構造函數,而它擁有一組帶參數的構造函數時
4:當類裡面的成員對象有自已的構造函數時,且有參數時(3、4歸為一類,為什麼必須使用,原理也是一樣的)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved