2011-03-04 92 views
3

對於類定義爲複數,只見兩種類型的定義:類成員初始化差異

定義1所

class Complex 
{ 
    private: 
     double re; 
     double im; 

    public: 
     Complex(float r,float i) {re = r; im = i;} 
     ~Complex() {}; 
}; 

定義2

class Complex 
{ 
    private: 
     double re; 
     double im; 

    public: 
     Complex(double r,double i): re(r), im(i) {} 
     ~Complex() {}; 
}; 

的第一個定義的外表對我來說,但我不太明白第二個定義,

Complex(double r,double i): re(r), im(i) {} 

工作嗎? 「re()」是什麼意思?

回答

4

它被稱爲初始值列表。在類的構造函數中,可以使用此語法初始化成員變量。所以在這裏,它相當於將語句re = r; im = i;放在構造函數的主體中。

對於POD變量如int,double和指針類型,初始化程序列表語法和正文中的常規賦值沒有區別。然而,對於const變量,引用,以及用不平凡的構造函數的對象,有一個重要的區別

  • 對於const變量和引用變量,它們必須在初始化列表中初始化。他們不能通過分配給他們在身體初始化。
  • 對於具有非平凡構造函數的對象,在初始化程序列表中如何初始化它們對應於被調用的構造函數。如果省略變量,則調用該對象的默認構造函數(如果該對象沒有默認構造函數,那麼這是編譯器錯誤)。

正因爲如此,它通常建議的對象與構造函數在初始化列表中得到初始化,以避免多餘的工作 - 如果你讓其默認構造方法從初始化列表忽略它,然後執行某種初始化運行在構造函數體中,你正在初始化它兩次,這可能是浪費。

例如:

class Example 
{ 
private: 
    std::string m_string; 
public: 
    Example() 
    { 
     // m_string is first initialized by the std::string default constructor, 
     // then we assign to it with operator=(const char *). 
     // This is inefficient. 
     m_string = "test"; 
    } 

    Example(int dummy) 
     : m_string("test") 
    { 
     // Better: we just call the std::string(const char*) constructor directly 
    } 
}; 
1

這是一個初始化列表。它將re的值設置爲r,並將值im設置爲i

通常情況下,您會看到使用初始化列表的性能增益,但知道何時不使用它也很重要。

1

首先,在C++中的整個類定義之後應該有一個分號。否則你的代碼將被公平地編譯。

反正

Complex(double r,double i): re(r), im(i) {} 

是簡單地放置的r爲重的價值和i的值到IM Complex類的構造函數。這是初始化類的值的另一種方式。

請注意,這樣的初始化列表對於初始化類中的成員類非常有用。這裏有一個例子:

class MemberClass 
{ 
    private: 
     int mValue; 

    public: 
     MemberClass(int value): mValue(value) {} 
}; 

class MemberHolder 
{ 
    private: 
     MemberClass mMember; 

    public: 
     MemberHolder(int value): mMember(value) {} 
}; 

初始化列表是使用類,而其他類中的默認構造函數重要。

2

構造函數Complex的第二種形式使用initialization lists,它們是初始化類成員的不同(和preferred way)。

re(...)東西意味着成員字段re應該使用它傳遞的任何參數來構造。

另一個例子 - 你可以創建像doubleint這樣的原語:

double d(5.0d); 
int i(5); 

這應該解釋在括號中列表是如何工作的。

1

在C++中沒有分配和初始化之間的區別。

a = 5; // assignment 
int b = 6; // initialization 
int b(6); // also initialization 

您的類的第一個版本在構造函數體內執行賦值。這是更昂貴的,因爲數據成員reim首先是默認構造的,然後分配它們的值。

在第二個版本構造函數初始化列表被使用。這裏的數據成員是用提供的值初始化的。這發生在一個步驟中,而默認的構造函數+賦值是兩個步驟。這樣更有效率。

通常,您應該優先初始化初始化列表中的數據成員,以在構造函數的主體內指定它們的值。但有一個警告。初始化列表中的數據成員按照它們在類中聲明的順序進行初始化,而不是按它們在初始化列表中出現的順序進行初始化。一般而言,您希望列表中成員的順序與他們的聲明順序相匹配。否則,如果一個數據成員的初始化取決於另一個數據成員的值,那麼最終可能很難找到錯誤。