標籤:
儘可能延後變數定義式的出現時間
我們知道定義一個對象的時候有一個不爭的事實,那就是分配記憶體。如果是我們自訂的對象,程式執行過程中會調用類的建構函式和解構函式。
我們打個比方,如果天下雨了,你帶把雨傘肯定是值得的。但是,如果你帶傘了,今天卻沒下雨,你是不是感覺自己虧了?的確,虧在了帶了卻沒用,所以傘就變成了累贅。
本節的關鍵就在於此,如果你定義一個變數或者對象沒有被使用,那麼就是不完美的代碼。
我們看一個程式碼片段:
std::string encryptPassword(const std::string& psaaword){ using namespace std; string encrypted; if(password.length()<MinimumPasswordLength) { throw logic_error("Password is too short"); } ……//加密密碼,把加密結果放到encrypted內 return encrypted;}
如果,拋出異常,上面的變數encrypted就沒有被使用,雖未被使用,可是卻要承受一次構造和一次析構的行為。
改進如下:
std::string encryptPassword(const std::string& psaaword) { using namespace std; if(password.length()<MinimumPasswordLength) { throw logic_error("Password is too short"); } string encrypted; ……//加密密碼,把加密結果放到encrypted內 return encrypted; }
改進的代碼跳過了異常,保證定義的encrypted一定被使用。可是我們知道如果能夠調用copy建構函式,就沒有必要調用default建構函式+賦值運算子函數。因為前者更高效。
我們繼續改進代碼:
std::string encryptPassword(const std::string& psaaword) { using namespace std; if(password.length()<MinimumPasswordLength) { throw logic_error("Password is too short"); } string encrypted(password);//定義+賦值 encrypt(encrpted); ……//加密密碼,把加密結果放到encrypted內 return encrypted; }
那麼我們在迴圈中怎麼貫徹這種思想呢?
對比一下代碼:
Widget w;//定義在迴圈外for(int i=0;i < n;++i) w=……; ……}for(int i=0;i<n;++i){ Widget w(……);//定義並賦值 ……}
第一個調用了1個建構函式+1個解構函式+n個賦值操作。第二個調用了n個建構函式+n個解構函式。我們此時需要斟酌一下是賦值操作的效率高還是構造+析構的效率高。事實上,如果雙方差距不大,最好選用後者,因為後者對象的範圍更小,可維護性和可理解性更強,更安全。
Effective C++ 條款26