只要你定义了一个变量而其类型带有一个构造函数或者析构函数,那么当程序的控制流到达这个变量定义式时,你就得承受构造成本;当这个变量离开作用域时,你就需要承受析构成本。即使这个变量最终未被使用,仍需要耗费这些成本,所以你应该避免这样的情况
// 这个函数过早的定义变量encrypted
std::string encryptPassword(const std::string & password){
using namespace std;
string encrypted;
if(password.length() < MinnumPasswordLength){
throw logic_error("password is too short");
}
...
return encrypted;
}
改进:
// 延后定义变量encrypted,知道真正需要它
std::string encryptPassword(const std::string & password){
using namespace std;
if(password.length() < MinnumPasswordLength){
throw logic_error("password is too short");
}
string encrypted;
...
return encrypted;
}
上面代码还是可以改进。因为encrypted使用的是默认构造函数定义的。我们知道,‘直接在构造中指定初值’比"通过默认构造函数构造出一个对象然后对它赋值"效率更高,也就是说,还可以改进:
std::string encryptPassword(const std::string & password){
using namespace std;
if(password.length() < MinnumPasswordLength){
throw logic_error("password is too short");
}
string encrypted(password);
...
return encrypted;
}
也就是说,这里的"尽可能延后"-----你不只应该延后变量的定义,直到非得使用变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止。如果这样,不仅能够避免构造(和析构)非必要的对象,还可以避免无意义的默认构造行为,
”但循环怎么办?“
// 方法A: 定义于循环外
Widget w;
for(int i = 0; i < n; i++){
w = xxxx(i);
}
// 方法B: 定义于循环内
for(int i = 0; i < n; i++){
Widget w(i);
}
除非:
- 你明确知道"赋值"成本比"析构+构造"成本低
- 你正在处理的代码对效率高度敏感
否则,你应该使用做法B