- 最近在看Scott Meyers的《Effective
C++》改善程序与设计的55个具体做法(第三版),水平有限,有些东西没能完全理解,捡一些自己能理解的并很容易记住的点来分享下!有的是原文的内容的直接摘抄,敬请谅解!
这条建议是:尽可能地延后定义式的出现时间。这么做的意义在于:可增加程序的清晰度并改善程序的效率。这对小程序来说可能体会的不深或者说影响不大,但是我们依然要保持良好的代码习惯和提高代码段的质量,不是吗?
作者给的解释是:只要你定义了一个变量而其类型带有一个构造函数或者析构函数,那么当函数的控制流到达这个变量定义式时,我们要承受构造成本,当离开作用域时,需要承受析构成本。即使这个变量最终你没有去使用它,这么成本仍然需要消耗,所以这种情况最好不要发生!
例如文中给的例子:
std::string encryptPasswoed(const std::string& password)
{
using namespace std;
string encrypted;
if (password.length()<MinimumPasswordLength)
{
throw...//抛出异常
}
....
return encrypted;
}
- 上面的例子如果真抛出异常,那么变量encrypted就不会被使用,所以我们可以在异常判断之后再进行定义:
std::string encryptPasswoed(const std::string& password)
{
using namespace std;
if (password.length()<MinimumPasswordLength)
{
throw...//抛出异常
}
string encrypted;
....
return encrypted;
}
- 这样是不是更合理一些呢?但是这么做也存在一些问题,下面我们看看文中是怎么说的。
以上第二段代码虽然延后了定义的时间,但是却没有任何实参作为初值,这意味着会调用其默认(default)的构造函数,书中条款4解释了为什么“通过默认的构造函数赋初值的效率比直接在构造时指定初值的效率差”,所以我们应该避免让它调用构造函数赋初值。所以最好的做法是:
std::string encryptPasswoed(const std::string& password)
{
using namespace std;
if (password.length()<MinimumPasswordLength)
{
throw...//抛出异常
}
string encrypted(password);//通过copy构造函数定义并初始化
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: 1个构造函数+1个析构函数+n个赋值操作 B:
n个构造函数+n个析构函数 分析:
如果classes的一个赋值成本低于一组构造加析构的成本,那么A会比较高效。根据(1)知道赋值成本比”构造”+”析构”的成本低,(2)正在处理的代码效率高度敏感的部分,否则选择B。一般情况下会选择A的写法。
- 最后,希望有更多的人能阅读并体会这书中的精髓,写出更高效更合理的代码!
时间: 2024-10-12 12:24:36