變數的推遲定義

2021-04-12 18:47:54 字數 1583 閱讀 2169

c語言中變數要放在模組頭部定義的規定;但在c++中,還是取消這種做法吧,它沒必要,不自然,而且昂貴。

如果定義了乙個有建構函式和析構函式的型別的變數,當程式執行到變數定義之處時,必然面臨構造的開銷;當變數離開它的生命空間時,又要承擔析構的開銷。這意味著定義無用的變數必然伴隨著不必要的開銷,所以只要可能,就要避免這種情況發生。

看看下面這個函式:當口令夠長時,它返回口令的加密版本;當口令太短時,函式丟擲logic_error型別的異常(logic_error型別在c++標準庫中定義,參見條款49):

// 此函式太早定義了變數"encrypted"

string encryptpassword(const string& password)

進行必要的操作,將口令的加密版本 

放進encrypted之中;

return encrypted;

}物件encrypted在函式中並非完全沒用,但如果有異常丟擲時,就是無用的。但是,即使encryptpassword丟擲異常,程式也要承擔encrypted構造和析構的開銷。所以,最好將encrypted推遲到確實需要它時才定義:

// 這個函式推遲了encrypted的定義,直到真正需要時才定義

string encryptpassword(const string& password)

string encrypted;

進行必要的操作,將口令的加密版本 

放進encrypted之中;

return encrypted;

}這段**還不是那麼嚴謹,因為encrypted定義時沒有帶任何初始化引數。這將導致它的預設建構函式被呼叫。大多數情況下,對乙個物件首先做的一件事是給它乙個什麼值,這通常用賦值來實現。"預設構造乙個物件然後對它賦值"比"用真正想要的值來初始化這個物件"效率要低得多。例如,假設encryptpassword中最難處理的部分在這個函式中進行:

void encrypt(string& s);      // s在此加密

於是encryptpassword可以象這樣實現(當然,它不是最好的實現方式):

// 這個函式推遲了encrypted的定義,直到需要時才定義,但還是很低效

string encryptpassword(const string& password)

更好的方法是用password來初始化encrypted,從而繞過了對預設建構函式不必要的呼叫:

// 定義和初始化encrypted的最好方式

string encryptpassword(const string& password)

這段**闡述了"盡可能"這三個字的真正含義。不僅要將變數的定義推遲到必須使用它的時候,還要盡量推遲到可以為它提供乙個初始化引數為止。這樣做,不僅可以避免對不必要的物件進行構造和析構,還可以避免無意義的對預設建構函式的呼叫。而且,在對變數進行初始化的場合下,變數本身的用途不言自明,所以在這裡定義變數有益於表明變數的含義。還記得在c語言中的做法嗎?每個變數的定義旁最好要有一條短注釋,以標明這個變數將來做什麼用。而現在,乙個合適的名字,再結合有意義的初始化引數,就可以實現每個程式設計師的夢想:通過可靠的變數本身來消除對它不必要的注釋。

推遲變數定義可以提高程式的效率,增強程式的條理性,還可以減少對變數含義的注釋。

盡可能地推遲變數的定義

是的,我們同意c語言中變數要放在模組頭部定義的規定 但在c 中,還是取消這種做法吧,它沒必要,不自然,而且昂貴。還記得嗎?如果定義了乙個有建構函式和析構函式的型別的變數,當程式執行到變數定義之處時,必然面臨構造的開銷 當變數離開它的生命空間時,又要承擔析構的開銷。這意味著定義無用的變數必然伴隨著不必...

條款32 盡可能地推遲變數的定義

此函式太早定義了變數 encrypted string encryptpassword const string password 進行必要的操作,將口令的加密版本 放進encrypted之中 return encrypted 物件encrypted在函式中並非完全沒用,但如果有異常丟擲時,就是無用...

C 箴言 只要有可能就推遲變數定義

在極大程度上,為你的類 包括類模板 和函式 包括函式模板 提供正確的定義是戰鬥的關鍵性部分。一旦你得到正確的結果,相應的實現很大程度上就是直截了當的。但是仍然有一些注意事項需要當心。過早地定義變數會對效能產生拖累。過度使用強制轉換會導致緩慢的,難以維護的,被微妙的 bug 困擾的 返回乙個類內部構件...