网站源码上传完后怎么做,百度做网站的费用,培训心得体会,石家庄网站建设销售电话只要你定义了一个变量而其类型带有一个构造函数或析构函数#xff0c;那么当程序的控制流#xff08;control flow#xff09;到达这个变量定义式时#xff0c;你便得承受构造成本#xff1b;当这个变量离开其作用域时#xff0c;你便得承受析构成本。即使这个变量最终并…只要你定义了一个变量而其类型带有一个构造函数或析构函数那么当程序的控制流control flow到达这个变量定义式时你便得承受构造成本当这个变量离开其作用域时你便得承受析构成本。即使这个变量最终并未被使用仍需耗费这些成本所以你应该尽可能避免这种情形。
或许你会认为你不可能定义一个不使用的变量但话不要说太早考虑下面这个函数它计算通行密码的加密版本而后返回前提是密码够长。如果密码太短函数会丢出一个异常类型为logic_error定义于C标准库见条款54
// 这个函数过早定义变量encrypted
std::string encryptPassword(const std::string password)
{using namespace std;string encrypted;if (password.length() MinimumPasswordLength){throw logic_error(Password is too short);}// ... 必要动作俾能将一个加密后的密码置入变量encrypted内return encrypted;
}对象encrypted在此函数中并非完全未被使用但如果有个异常被丢出它就真的没被使用。也就是说如果函数encryptPassword丢出异常你仍得付出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;// ... 必要动作俾能使一个加密后的密码置入变量encrypted内return encrypted;
}但是这段代码仍然不够秾纤合度形容某事恰到好处因为encrypted虽获定义却无任何实参作为初值。这意味调用的是其default构造函数。许多时候你该对对象做的第一次事就是给它个值通常是通过一个赋值动作达成。条款4曾解释为什么“通过default构造函数构造出一个对象然后对它赋值”比“直接在构造时指定初值”效率差。那个分析当然也适用于此。举个例子假设encryptPassword的艰难部分在以下函数中进行
void encrypt(std::string s); // 在其中适当地对s加密于是encryptPassword可实现如下虽然还不算是最好的做法
// 这个函数延后encrypted的定义直到需要它为止
// 但此函数仍然有着不该有的效率低落
std::string encryptPassword(const std::string password)
{// ... 检查length如前std::string encrypted; // default-construct encryptedencrypted password; // 赋值给encryptedencrypt(encrypted);return encrypted;
}更受欢迎的做法是以password作为encrypted的初值跳过毫无意义的default构造过程
// 终于这是定义并初始化encrypted的最佳做法
std::string encryptPassword(const std::string password)
{// ... 检查长度std::string encrypted(password); // 通过copy构造函数定义并初始化encrypt(encrypted);return encrypted;
}这让我们联想起本条款所谓“尽可能延后”的真正意义。你不只应该延后变量的定义直到非得使用该变量的前一刻为止甚至应该尝试延后这份定义直到能够给它初值实参为止。如果这样不仅能够避免构造和析构非必要对象还可以避免无意义的default构造行为。更深一层说以“具明显意义之初值”将变量初始化还可以附带说明变量的目的。
“但循环怎么办”你可能会感到疑惑。如果变量只在循环内使用那么把它定义于循环外并在每次循环迭代时赋值给它比较好还是该把它定义于循环内也就是说下面两个一般性结构哪一个比较好
// 方法A定义于循环外
Widget w;
for (int i 0; i n; i)
{w 取决于i的某个值;// ...
}// 方法B定义于循环内
for (int i 0; i n; i)
{Widget w(取决于i的某个值);// ...
}这里把对象的类型从string改为Widget以免造成读者对于“对象执行构造、析构、或赋值动作所需的成本”有任何特殊偏见。
在Widget函数内部以上两种写法的成本如下 做法A1个构造函数1个析构函数n个赋值操作。
做法Bn个构造函数n个析构函数。
如果class的一个赋值成本低于一组构造析构成本做法A大体而言比较高效。尤其当n值很大的时候。否则做法B或许较好。此外做法A造成名称w的作用域覆盖整个循环比做法B更大有时那对程序的可理解性和易维护性造成冲突。因此除非1你知道赋值成本比“构造析构”成本低2你正在处理代码中效率高度敏感performance-sensitive的部分否则你应该使用做法B。
请记住 尽可能延后变量定义式的出现。这样做可增加程序的清晰度并改善程序效率。