【Effective C++】读书笔记 Part5 实现
条款26:尽可能延后变量定义式的出现时间
非循环中的变量定义
尽量延后变量定义式的出现时间,主要包括两个方面:
- 直到必须使用变量的时候才对其进行定义,否则就不定义。这样子可以减定义对象时候需要的构造函数和析构函数的开销。
- 有初值实参的时候再进行定义变量,比直接使用默认构造函数再赋值的效率要高。
如下函数
void encrypt(std::string &s)
{
//具体加密操作;
}
std::string encryptPassword(const std::string &password)
{
using namespace::std;
string encrypted;
//流控制,判断密码长度
if(password.length() < MinimumPasswordLength)
{
throw loginc_error("Password is too short");
}
//具体获取密码加密操作
encrypted = password;
encrypt(encrypted);
return encrypted;
}
考虑一下上述函数的缺陷:
- if流控制可能会导致过早的结束函数块,显然在流控制之前并没有任何语句需要encrypted变量。但是即使流控制提早结束,仍然需要encrypted的构造函数和析构函数的开销。
- 对于encrypted变量,先使用默认构造函数进行定义,在进行赋值操作。显然不如直接采用初值进行构造更有效率。
相应的改良版本:
void encrypt(std::string &s)
{
//具体加密操作;
}
std::string encryptPassword(const std::string &password)
{
using namespace::std;
//流控制,判断密码长度
if(password.length() < MinimumPasswordLength)
{
throw loginc_error("Password is too short");
}
//具体获取密码加密操作
string encrypted(password);
encrypt(encrypted);
return encrypted;
}
如上版本,就实现了尽可能延后变量定义式的出现时间。
循环中的变量定义
考虑如下两个版本,一个版本将循环中将要使用的变量定义在循环外部,一个版本将循环中将要使用的变量定义在循环内部。
A版本:
Widget w
for(int i = 0; i < n; ++i)
{
w = 取决于i的值;
}
B版本:
for(int i = 0; i < n; ++i)
{
Widget w(取决于i的值);
}
对于A版本,需要一次构造,一次析构,n次赋值操作。
对于B版本,需要n个构造函数,和n个析构函数。
对于class而言,如果其赋值成本低于一组构造+析构成本,做法A大体上而言高于B版本,否则则版本B更好。
此外A版本,名称w的作用域覆盖的范围更广,有时候可能会对程序的可理解性和易维护性造成冲突。但是也有可能某些情况下仍需要在循环外部访问w。
所以除非你知道赋值成本比”析构+构造”成本低,或者你正在处理代码中效率高度敏感的部分,或者你有特殊的需求,否则应该选择做法B。