条款26 尽可能延后变量定义出现的时间

来源:互联网 发布:stc单片机官网 编辑:程序博客网 时间:2024/05/18 00:23
尽可能延后变量定义的出现,这样可以增加程序的清晰度并改善程序效率 当定义一个变量(尽管从未使用),当程序控制流到达这个变量定义时,仍然会耗费构造和析构成本。考虑下述代码:
//过早定义变量s1       std::string fun1(const std::string& s1)       {              using namespace std;              string s2;              if(s1.length()<minlength)              {                     throw error("s1 is too short");  //s1太短 则抛出异常              }              ...       //必要操作                     return s2;       }

       上述代码在抛出异常,并没有使用s2时,你仍需花费s2的构造和析构成本,改进如下:
//延后s2定义 直到真正需要它       std::string fun1(const std::string& s1)       {              using namespace std;              if(s1.length()<minlength)              {                     throw error("s1 is too short");  //s1太短 则抛出异常              }              string s2;              ...   //必要操作              return s2;       }
改进后的代码仍然不够完善,因为s2并无任何实参作为初值。条款4说明“通过default函数构造一个对象然后对它赋值”比“构造对象是直接指定初值”效率差。该分析同样适用于此代码。
考虑以下代码:假设s2的主要操作在以下函数中进行void fun2(std::string&  s);  //在适当的地方处理s
于是fun1实现如下,虽然还不完善
std::string fun1(const std::string& s1)       {       ...          //同前 检查length       std::string s2;  //默认构造s2       s2=s1;           //赋值给s2;       fun2(s2);       return s2;       }
       根据“直接在构造时指定初值”改进代码如下:
//定义并初始化s2的最佳做法       std::string fun1(const std::string& s1)       {              ...  //同前              string s2(s1);    //通过复制构造函数              fun2(s2);              return s2;       }

这样我们想到“尽量延后变量定义”的真正含义,不应只延后变量定义直到使用该变量的前一刻为止,更应是延后变量定义直到能给它初始值实参为止。
这样可以避免无意义的构造和析构行为,也能避免无意义的默认构造行为
 
当遇到循环时,应定义变量于循环内还是循环外?考虑下述代码:
//方法A  定义于循环外       Widget w;       for(int i=0;i<n;++i)       {              w=取决于i的某个值;              ...       }   //方法B 定义于循环内       for(int i=0;i<n;++i)       {              Widget w(取决于i的某个值);              ...       }

方法A:1构造+1析构+n赋值方法B:n构造+n析构
很显然,如果成本  1赋值<(1构造+1析构),应先A方案,特别是当n很大时。否则选B方案。
此外,A定义的w的作用域(覆盖整个循环)比B大,有时会对程序的可理解性和易维护性造成冲突。
所以除非1、知道赋值成本比构造加析构成本低,2、正在处理代码中效率高度敏感部分,时选用A,否则应该选用B方案。
0 0
原创粉丝点击