首页 > 代码库 > 条款32: 尽可能地推迟变量的定义

条款32: 尽可能地推迟变量的定义

// 此函数太早定义了变量"encrypted"string encryptPassword(const string& password){  string encrypted;//默认构造函数初始化  if (password.length() < MINIMUM_PASSWORD_LENGTH) {     throw logic_error("Password is too short");  }  进行必要的操作,将口令的加密版本    放进encrypted之中;  return encrypted;}

对象encrypted在函数中并非完全没用,但如果有异常抛出时,就是无用的。但是,即使encryptPassword抛出异常(见条款M15),程序也要承担encrypted构造和析构的开销。所以,最好将encrypted推迟到确实需要它时才定义:

// 这个函数推迟了encrypted的定义,// 直到真正需要时才定义string encryptPassword(const string& password){  if (password.length() < MINIMUM_PASSWORD_LENGTH) {    throw logic_error("Password is too short");  }  string encrypted;  进行必要的操作,将口令的加密版本    放进encrypted之中;  return encrypted;}

这段代码还不是那么严谨,因为encrypted定义时没有带任何初始化参数。这将导致它的缺省构造函数被调用。大多数情况下,对一个对象首先做的一件事是给它一个什么值,这通常用赋值来实现。条款12说明了为什么"缺省构造一个对象然后对它赋值"(调用缺省构造函数初始化和拷贝赋值运算符赋值)比"用真正想要的值来初始化这个对象"(显式调用构造函数初始化)效率要低得多。这一论断在此一样适用。例如,假设encryptPassword中最难处理的部分在这个函数中进行:

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

于是encryptPassword可以象这样实现(当然,它不是最好的实现方式):

// 这个函数推迟了encrypted的定义,// 直到需要时才定义,但还是很低效string encryptPassword(const string& password){  ...                      // 同上,检查长度  string encrypted;        // 缺省构造encrypted  encrypted = password;    // 给encrypted赋值  encrypt(encrypted);  return encrypted;}

更好的方法是用password来初始化encrypted,从而绕过了对缺省构造函数不必要的调用:

// 定义和初始化encrypted的最好方式string encryptPassword(const string& password){  ...                             // 检查长度  string encrypted(password);     // 通过拷贝构造函数定义并初始化  encrypt(encrypted);  return encrypted;}

 

你不仅要将变量的定义推迟到必须使用它的时候,还要尽量推迟到可以为它提供一个初始化参数为止。这样做,不仅可以避免对不必要的对象进行构造和析构,还可以避免无意义的对缺省构造函数的调用。而且,在对变量进行初始化的场合下,变量本身的用途不言自明,所以在这里定义变量有益于表明变量的含义。