读书笔记_Effective_C++_条款二十六:尽可能延后变量定义式的出现时间
这个条款从字面意思还是很好理解的,就是在使用这个变量前才去定义,而不是很早就定义了它,而在很后面的时候才去使用。这个条款只适用于对变量声明位置没有要求的语言,比如C++。对于像C或者一些脚本语言,语法要求变量声明放在函数开始处,这个条款就不能使用了。
但其实从使用的角度而言,如果不是语法的硬性要求,还是在变量使用前再去定义变量的做法比较好。这有几点原因,最直观的就是可读性比较好,程序员在阅读代码时,看到一个陌生的变量名,不用向上翻好几页才看到它的定义类型,而且对于开发者而言,也不会出现前面定义了一个变量,之后又忘记使用它的情况。另一个原因就是可以节省资源,考虑以下的代码:
void example(const A& parm)
{
A a;
fun(); // 这个fun()函数不会使用a
a = parm;
…
}
假设存在一个类A,如果在程序的开始处就定义它的对象a(调用了构造函数),中间夹了一个函数fun(),这个函数可能抛出异常,导致下面的程序不去执行,这样对象a的构造函数就白调用了,既浪费了空间,也浪费了时间。
所以改进的做法就是:
void example(const A& parm)
{
fun();
A a;
a = parm;
…
}
这下如果fun()抛出异常,那么也不会浪费资源了,但这里还是有一个比较“废”的地方,就是调用了构造函数,也调用了赋值运算,但这两个操作的目的都是给a一个值,所以可以将这两个操作进行精减,直接调用A的拷贝构造函数,像这样:
void example(const A& parm)
{
fun();
A a(parm);
…
}
赋值运算就不用调用了。
书上还讲到了一个写代码常见的问题,就是循环中的变量定义,是放在循环内比较好呢,还是放在循环外比较好呢?看下面的例子:
// 放在循环外
A a;
for(int i = ; i < N; ++i)
{
a = a * b[i];
…
}
//后面不再使用a
// 放在循环内
for(int i = ; i < N; ++i)
{
A a(b[i]);
…
}
//后面不再使用a
分析一下,如果采用放在循环外的方法,代价是1次构造+1次析构+N次赋值;如果采用放在循环内的方法,代价是N次构造+N次析构。所以究竟哪个更好,还是要看构造函数、析构函数VS赋值操作,哪一个比较废。
但如果两方的代价差不多,还是推荐放在循环内的做法,因为这种做法使得a的作用域局限于for循环内,符合作用域能小就小的编程原则。
最后总结一下:
尽可能延后变量定义式的出现,这样做可增加程序的清晰度并改善程序效率。
读书笔记_Effective_C++_条款二十六:尽可能延后变量定义式的出现时间的更多相关文章
- Effective C++:条款26:尽可能延后变量定义式的出现时间
(一) 那么当程序的控制流到达这个变量定义时.变承受构造成本:当变量离开作用域时.便承受析构成本. string encryptPassword(const std::string& pass ...
- 读书笔记_Effective_C++_条款二十九:为“异常安全”而努力是值得的
还是举书上的例子: void PrettyMenu::changeBackground(std::istream& imgSrc) { lock(&mutex); delete bgI ...
- 读书笔记_Effective_C++_条款四十六:需要类型转换时请为模板定义非成员函数
这个条款可以看成是条款24的续集,我们先简单回顾一下条款24,它说了为什么类似于operator *这样的重载运算符要定义成非成员函数(是为了保证混合乘法2*SomeRational或者SomeRat ...
- 读书笔记_Effective_C++_条款三十六:绝不重新定义继承而来的non-virtual函数
这个条款的内容很简单,见下面的示例: class BaseClass { public: void NonVirtualFunction() { cout << "BaseCla ...
- 读书笔记_Effective_C++_条款二十八:避免返回handlers指向对象内部成分
举个例子: class Student { private: int ID; string name; public: string& GetName() { return name; } } ...
- 读书笔记_Effective_C++_条款二十五: 考虑写出一个不抛出异常的swap函数
在之前的理论上调用对象的operator=是这样做的 void swap(A& x) { std::swap(a, x.a); } A& operator=(const A& ...
- 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数
class A { private: int a; public: A(int x) :a(x){} A operator*(const A& x) { return A(a*x.a); } ...
- 读书笔记_Effective_C++_条款二十二:将成员变量声明为private
1.格式统一 在调用的时候,不会去想有没有(),一律是有get(),或者set()之类的. 2.封装 能直接访问得越少,表明封装性越高, 封装性越高,我们的顾虑就少了, 例如:我们a.data*0.9 ...
- Effective C++ -----条款26:尽可能延后变量定义式的出现时间
尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率.
随机推荐
- Ubuntu16.04安装记
Ubuntu16.04安装记 基本信息: 华硕笔记本 Windows 10 家庭版 处理器:Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz 2.71GHz 已安装的内 ...
- docker简单介绍(资料收集总结)
[前言] 首先,感谢我的leader总是会问我很多技术的基本资料,让我这个本来对于各种技术只知道操作命令不关注理论知识的人,开始重视理论资料. 关于docker的操作步骤等等,都是之前学习的,现在补上 ...
- uWSGI+Nginx+Flask在Linux下的部署
搞了一天多,终于搞通了uWSGI的部署原理,下面总结一下遇到的一些坑,希望给读者能够少走弯路. 简单来说,uWSGI是一个web服务器,Nginx进行反向代理的其实跟这些服务器可以说没有 ...
- IndexWriterConfig的各个配置项说明(转)
1.Analyzer:分析器 2.matchVersion:所用Lucene的版本 3.ramBufferSizeMB:随机内存 默认为16M. 用于控制buffer索引文档的内存上限,如果buffe ...
- 关于语义化版本(semantic versioning or SemVer)
1 为什么要有SemVer? SemVer用来规范组件之间的依赖版本,它使用一个版本号来传递出组件的API的变化情况. 在理解这规范之后,看一眼依赖包的版本号,就知道API的变化(兼容性)程度,方便 ...
- 用JDK自带的监控工具jconsole来监控程序运行
工具目录:C:\Program Files\Java\jdk1.6.0_06\bin\jconsole.exe 效果如下:监控类ThreadPoolExecutorTest 的运行 选择我们运行的程序 ...
- IE8/9的几个前端bug解决方案
最近做的东西需要兼容IE……啊真是令人忧伤…… 解决低版本IE的buggy inline-block 低版本的IE只对本身inline的元素能用inline-block,而本身为block的元素需要设 ...
- 关于HTML5 boilerplate 的一些笔记
最近在研究HTML5 boilerplate的模版,以此为线索可以有条理地学习一些前端的best practice,好过在W3C的文档汪洋里大海捞针……啊哈哈哈…… 开头的IE探测与no-js类是什么 ...
- [Matlab]Upper Triangularization & Back Substitution代码
用来做数值计算作业的代码,来自Numerical Methods Using Matlab (4th Edition) [John H. Mathews, Kurtis K. Fink],改了一下注释 ...
- 小甲鱼C++笔记(上)1-24
一 OO思想:每个对象都是一个完整的独立的个体,由相关的属性和行为组合与外界分隔 OO思想的特点:1封装 把对象的属性和方法结合成一个独立的系统单位,并尽可能隐藏内部细节 2抽象 对一类公共问题进行统 ...