Effective C++笔记(一)——条款26-29
条款26:尽可能延后变量定义式的出现时间
为何要尽量延后?
当程序中途跳出而导致变量未被使用,但是必须进行构造和析构。
最佳初始化变量
直接在构造时指定初值比构造之后再赋值效率高(条款4)
...
std::string encrypted(password);
...
循环内变量定义在循环内还是循环外?
程序A:定义于循环外
//方法A:循环外定义
POINT point;
for (int i = 0; i < 1000000000; i++)
{
point = tmp;
//tmp = point;
}
程序B:定义于循环内
//方法B:循环内定义
for (int i = 0; i < 1000000000; i++)
{
POINT point(tmp);
//tmp = point;
}
测试程序
int PostponeVariable()
{
POINT tmp;
tmp.x = 12;
tmp.y = 13;
clock_t start = clock();
//方法A:循环外定义
POINT point;
for (int i = 0; i < 1000000000; i++)
{
point = tmp;
//tmp = point;
}
clock_t end = clock();
printf("A:%ld\n", (end - start));
start = clock();
//方法B:循环内定义
for (int i = 0; i < 1000000000; i++)
{
POINT point(tmp);
//tmp = point;
}
end = clock();
printf("B:%ld\n", (end - start));
return 0;
}
结果
A:2953
B:2774
请按任意键继续. . .
全部都是A比B执行的快,之前一直自以为是的觉得放在循环外效率比较高!
条款27:尽量少做转型动作
- 尽量避免转型,特别是dynamic_casts,使用无转型设计代替有转型设计
- 一定要转型时,试着将其影藏于函数背后
- 尽可能使用C++新式转型
条款28:避免返回handles指向对象的内部
class Point{
public:
Point(int x, int y);
...
void setX(int newVal);
void setY(int newVal);
...
};
struct RectData{
Point ulhc;
Point lrhc;
};
class Rectangle{
...
Point& upperLeft()const {return pData->ulhc;}
Point& lowerRight()const {return pData->lrhc;}
private:
std::tr1::shared_ptr<RectData> pData;
};
const对象被修改:
Point coord1(0,0);
Point coord2(100,100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().setX(50);//现在rec变成从(50,0)到(100,100)
修正:
class Rectangle{
...
const Point& upperLeft()const {return pData->ulhc;}
const Point& lowerRight()const {return pData->lrhc;}
private:
std::tr1::shared_ptr<RectData> pData;
};
避免返回指向对象内部部件的句柄(引用、指针或迭代器)。这样做可以增强封装性,帮助 const 成员函数拥有更加“ const ”的行为,并且使“野句柄”出现的几率降至最低。
条款29:为“异常安全”而努力
1. 修改菜单背景
class PrettyMenu{
public:
...
void changeBackground(std::istream& imgSrc);
...
private:
Mutex mutex;
Image* bgImage;
int imageChanges;
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
lock(&mutex);
delete bgImage;
++imageChanges;
bgImage = new Image(imgSrc);
unlock(&mutex);
}
2. 异常安全条件
- 不泄漏任何资源:若new Image(imgSrc)异常,则unlock永不解锁
- 不允许数据破坏:若new Image(imgSrc)异常,则bgImage指向被删除的指针,且imageChanges已被修改,导致未成功执行却修改了数据。
3. 对象管理资源:解决资源泄漏
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
Lock ml(&mutex);//来自条款14;
delete bgImage;
++imageChanges;
bgImage = new Image(imgSrc);
}
4. 异常安全函数保证
- 基本承诺:异常抛出时,保持有效状态,没有对象或数据结构被破坏
- 强烈保证:异常出现时,程序状态不改变,成功则完全成功,失败则会到之前状态
- 不抛掷(nothrow)保证:承诺不抛出异常
5. 基本承诺
class PrettyMenu{
...
std::tr1::shared_ptr<Image> bgImage;
...
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
Lock ml(&mutex);
bgImage.reset(new Image(imgSrc));
++imageChanges;
}
6. 强烈保证:copy and swap
struct PMImpl{
std::tr1::shared_ptr<Image> bgImage;
int imageChanges;
};
class PrettyMenu{
...
private:
Mutex mutex;
std::tr1::shared_ptr<PMImpl> pImpl;
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
using std::swap;
Lock ml(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc)); //修改副本
++pNew->imageChanges;
swap(pImpl, pNew);//置换数据
}
Effective C++笔记(一)——条款26-29的更多相关文章
- Effective C++ 笔记:条款 32 确定你的public继承塑造出正确的is-a关系
32 : Make sure public inheritance models "is-a." 0 引言 Inheritance and Object-Oriented Desi ...
- Effective C++ 笔记:条款 31 将编译关系降至最低
31 : Minimize compilation dependencies between files 1 这关乎C++的类(或说都是类惹的祸) 1.1 C++类定义式的问题 C++类定义式不只叙述 ...
- Effective C++ 笔记:条款 30 inline
30 : Understand the ins and outs of inlining 1 inline申请书 1.1 类内部实现函数包含隐藏的inline申请 class Human { publ ...
- Effective C++ 笔记:条款 34 实现继承和接口继承
Differentiate between inheritance of interface and inheritance of implementation. 行为含义 声明一个pure virt ...
- Effective C++ 笔记:条款 33 避免继承导致的名称遮掩
Avoid hiding inherited names 作用域(scopes)所带来的名称二义性,c++编译器会寻找指涉(refer to)的对象并实现名称遮掩规则(name-hiding rule ...
- EC读书笔记系列之14:条款26、27、28、29、30、31
条款26 尽可能延后变量定义式的出现时间(Lazy evaluation) 记住: ★尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率 ----------------------- ...
- [Effective JavaScript 笔记]第3章:使用函数--个人总结
前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...
- Effective C++笔记:实现
条款26:尽可能延后变量定义式的出现时间 博客地址:http://www.cnblogs.com/ronny/ 转载请注明出处! 有些对象,你可能过早的定义它,而在代码执行的过程中发生了导常,造成了开 ...
- Effective C++笔记05:实现
条款26:尽可能延后变量定义式的出现时间 博客地址:http://blog.csdn.net/cv_ronny 转载请注明出处! 有些对象,你可能过早的定义它,而在代码运行的过程中发生了导常,造成了開 ...
随机推荐
- hdu3724Encoded Barcodes(Trie tree)
题目请戳这里 题目大意:给n个字符串,给m个询问,每个询问给k个条形码.每个条形码由8个小码组成,每个小码有相应的宽度,已知一个条形码的宽度只有2种,宽的表示1,窄的表示0.并且宽的宽度是窄的宽度的2 ...
- Flashback Version Query、Flashback Transaction Query快速闪回细粒度数据
Flashback Version Query 闪回版本查询 使用Flashback Version Query 返回在指定时间间隔或SCN间隔内的所有版本,一次commit命令就会创建一个版本. ...
- PHP开发Android应用程序(转)
第一部分是指在Android系统的手机上直接写PHP脚本代码并立即运行:第二部分则继续讲解如何把写好的PHP脚本代码打包成akp安装文件. 首先,在手机上安装两个apk包. 一个是SL4A(Scrip ...
- Qt Sqlite封装类SqliteUtil
在网上找了很久关于Qt访问Sqlite数据库的封装类,但是没能找到一个很好的访问调用类,自己写了一个出来,在这里分享一下,希望能对大家有所帮助,小弟不才,写代码没多少经验,如果有什么不恰当之处,请批评 ...
- Spark HA 的搭建
接hadoop HA的搭建,因为你zookeeper已经部署完成,所以直接安装spark就可以 tar –xzf spark-1.6.1-bin-hadoop2.6.tgz -C ../service ...
- 洛谷 P1412 经营与开发
/* 粘一下开始写的暴力吧 虽然没啥价值 */ #include<iostream> #include<cstdio> #include<cstring> #inc ...
- JavaScript代码性能优化总结
JavaScript 代码性能优化总结 尽量使用源生方法 javaScript是解释性语言,相比编译性语言执行速度要慢.浏览器已经实现的方法,就不要再去实现一遍了.另外,浏览器已经实现的方法在算法方面 ...
- 安装 vs2005, vs2008 报错
最近重新装了系统之后,在安装 vs2005, vs2008 到如下类似的错误,苦苦两天没有解决.不要问为什么是 vs2005,vs2008, 因为原有的项目就是老版本. 无意间在网上看到一句话,大意是 ...
- 刚接触js感觉好吃力啊
我是一个新手,最近刚刚开始学习js这门语言,感觉好难,有一种无从下手的感觉,不知道应该从哪里学习,虽然也看了很多的书,但是对于一个没有计算机基础的人来说,真的是一种煎熬,每一个名词都要去查.万事开头难 ...
- js添加onclick函数
document.getElementById('Add').setAttribute("onclick",AddNum()); 相当于不停的调用Addnum函数 应改成docum ...