考虑下面函数:
std::string encryptPassword(const std::string & password)
{
using namespace std;
string encrypted;
if(password.length() < MinimumPasswordLength)
{
throw logic_error("Password is too short");
}
...
return encrypted;
}
如果有异常抛出,encrypted
就完全没有被使用,此时你仍得付出encrypted
的构造成本和析构成本。所以最好延后encrypted
的定义式,直到确实需要它:
std::string encryptPassword(const std::string & password)
{
using namespace std;
if(password.length() < MinimumPasswordLength)
{
throw logic_error("Password is too short");
}
string encrypted;
...
return encrypted;
}
但是这段代码还有个问题,encrypted
虽然定义了却没有任何实参作为初值,这意味着调用的是其默认构造函数,条款4已经说过了,使用默认构造函数出一个对象然后对它赋值效率比较差。
更好的做法是:以password
作为encrypted
的初值,跳过毫无意义的默认构造过程
std::string encryptPassword(const std::string & password)
{
using namespace std;
if(password.length() < MinimumPasswordLength)
{
throw logic_error("Password is too short");
}
string encrypted(password);
...
return encrypted;
}
尽可能延后的真正意义是:你不应该只延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义知道能够给它初值实参为止。
但是循环怎么办?
考虑下面两个结构,哪一个比较好?
//做法A
Student A;
for(int i = 0; i < n; ++i)
{
A = i的某个值
...;
}
//做法B
for(int i = 0; i < n; ++i)
{
Student A(i的某个值);
}
做法A:1个构造函数 + 1个析构函数+ n个赋值操作
做法B : n个构造函数+n个析构函数
如果赋值操作低于构造和析构成本,A比较好,尤其当n比较大的时候,否则做法B可能会更好。
此外做法A造成w的作用域比做法B更大,有时会对程序的可理解性和易维护性造成冲突.
总结:
尽可能延后变量定义式的出现,这样做可增加程序的清晰度并改善程序效率