C++之初始化問題


首先,我們應該明確的是在C++中初始化不是賦值,因為初始化是必要的,如果讀取了未初始化的值將會導致不明確的行為。初始化指創建變量並且給它賦初值,而賦值則是擦除對象的當前值並用新值代替。C++支持兩種初始化變量的方式:復制初始化和直接初始化:

int ival(1000);//直接初始化是將初始化式放在括號里
int ival=1000;//復制初始化是用等號(=)
那么這兩種方式有什么區別呢?我們可以這樣認為,對於內置類型來說,復制初始化和直接初始化幾乎沒有差別,對於類類型來講,當創建類類型對象時,初始化的復制形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然后使用復制構造函數將那個臨時對象復制到正在創建的對象:

string strVal1="2014";//編譯器首先調用接受一個字符串形參的string構造函數,創建一個臨時對象,然后,編譯器使用

string復制構造函數將strVal1初始化為那個臨時對象的副本

string strVal2("2014");//直接調用string類中匹配的構造函數


string strVal3 = string();//先使用默認構造函數創建一個臨時對象,使用復制構造函數將那個臨時對象復制到正在創建的對象

string strVal4;//直接運行strVal4的默認構造函數
其次,講講變量的初始化規則:
內置類型變量的初始化是否自動初始化取決於變量定義的位置,在函數體外定義的變量都初始化成0,在函數體內定義的內置變量不進行自動初始化,因此,實際編程中,建議每個內置類型的對象都要初始化,雖然有時候這樣做並不總是必須的。類類型的初始化與它的默認構造函數是否存在有關,只要它有默認構造函數,則不管變量在那里定義,我們都可以不提供初始化式,相反,我們則需要每個定義都必須提供顯式的初始化式,如:


string emptyStr;//因為類中定義了默認構造函數來初始化string變量為空字符串
接下來,我們來看看關於類類型的兩種構造函數的寫法
法一:
TestOne::TestOne(const std::string &name,const::string & address,
const std::list<PhoneNumber>& phones)
{
theName=name;
theAddress=address;//注意這些都是賦值,而非初始化
thePhones=phones;
}
法二:
TestTwo::TestTwo(const std::string &name,const::string & address,
const std::list<PhoneNumber>& phones)
:theName(name),
theAddress(address),//現在這些都是初始化
thePhones(phones)
{ }//現在,構造函數體不必有任何動作

這兩種方法都可以滿足我們的需要,但是效果是不一樣的。
C++中規定,對象的成員變量的初始化動作發生在進入構造函數本體之前,在法一中,theName,theAddress,thePhone這些成員的初始化發生的時間是在這些成員的默認構造函數被自動調用之時,也就是它們真正被初始化的時候,因此,它們發生的時間比進入當前構造函數的時間更早。因此,法一相當於對這些已經被默認構造函數初始化的成員變量再次進行賦值,默認構造函數做了無用功。而法二,則是直接就通過成員的構造函數來初始化的,一步到位。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM