Effective C++ 重要条款
学习c++的童鞋们,这本书不能错过,最近在学校图书馆借来这本书,准备好好啃啃它了,先把它的基本内容过一遍吧。
改变旧有的的C习惯 |
条款1:尽量以const和inline取代#define。
条款2:尽量以<iostream>取代<stdio.h>
条款3:尽量以new和delete取代malloc和free。
条款4:尽量使用C++风格的注释形式。
条款5:使用相同形式的new和delete。
内存管理篇 |
条款6:记得在destructor中以delete对付pointer members。
条款7:为内存不足的状况预做准备。
条款8:撰写operator new和operator delete 时应遵行的公约。
条款9:避免遮掩了new的正规形式。
条款10:如果你写了一个operator new,请对应写一个operator delete。
对于条款1就没什么好说的了,建议我们不要使用宏,改用常量,如const double ASPECT_RACIO=1.653,取代define ASPECT_RACIO 1.653。
条款2是对于输入输出而言,我们应该尽量采用cin,cout。
条款3说明在c++中尽量用new取代malloc,如string *stringArray2=new string[10],当释放内存时delete[]stringArray2,数组中的每个对象的destructor都会被调用一遍。
条款10对于分配内存进行了详细的说明,我们自己写operator new的时候,一定不要忘了写operator delete,否则就Memory leak了。
下面看段代码,书上说的是写一个Pool类来配置内存,由它负责申请和释放内存,首先定义一个Pool类。
class Pool
{
public:
Pool(size_t n); //首先声明需要空间的大小
void *alloc(size_t n); //申请内存
void free(void *p,size_t n); //释放内存
~ Pool();
}; class AirPlane
{
public:
AirPlane();
~ AirPlane();
static void* operator new(size_t size);
static void operator delete(void *p,size_t size); private:
AirPlaneRep* rep;
static Pool memPool; }; inline void* AirPlane::operator new(size_t size)
{
return memPool.alloc(size);
}
inline void AirPlane::operator delete(void *p,size_t size)
{
return memPool.free(p,size);
} Pool AirPlane::memPool(sizeof(AirPlane)); //用sizeof()初始化memPool,大小为一个Airplane;
通过这种方法可以改善程序效率,重点还是需要operator new和operator delete 二者合作。
条款11:如果class内动态配置有内存,请为此class声明一个copy constructor和一个assignment运算符。这就话也可以这么理解,当你的class中拥有任何指针的时候,那么类最好拥有自己的copy constructor和assignment operator。
class TableString
{
public:
TableString(const char*);
~ TableString(); private:
char* data;
}; TableString:: TableString(const char*value)
{
if (value)
{
data=new char[strlen(value)+1];
strcpy_s(data,strlen(value)+1,value);
}
else
{
data=new char[1];
*data='\0';
}
} TableString::~ TableString()
{
delete[]data;
}
int _tmain(int argc, _TCHAR* argv[])
{
TableString a("hello");
TableString b("nihao");
b=a;
return 0;
}
例如上面这段代码里面,类TableString有自己的指针变量,却没有定义自己的复制构造函数和赋值函数,当执行完b=a这一句的时候,内存就已经泄漏了。首先,b原先的内存没有释放,其次,a和b的指针指向相同的字符串,当其中一个离开生存空间,就会调用它的析构函数,删除内存,另外一个指针指向的内存就为空了。
构造、析构和赋值操作 |
条款15:令operator==传回“*this的reference”
String& String::operator=(const String& rhs)
{
return *this; //传回一个引用,指向左侧对象
}
String& String::operator=(const String& rhs)
{
return rhs; //指向右侧对象
}
定义的第二个赋值操作符将无法通过编译,因为rhs是一个引用型const常量,而传回的却是非const引用,而我们把const去掉的话也不能解决问题,不能把const常量传递给非const的参数变量。所有,我们别无选择,只能return *this。
条款16:在operator=中为所有的datamembers设定(赋值)内容
这个条款大概的意思就是在派生类中必须对基类的成员进行一个初始化,在派生类的构造函数中可以调用基类的构造函数进行成员的初始化,为base制定初值。
条款17:在operator=中检查是否“自己赋值给自己”
成员在赋值的时候,又可能出现自己赋值给自己的情况,例如:String a="hello world";a=a;如果你在赋值运算符中没有对这个进行检验的话,那么程序写出来后果将不堪设想。我们一般的做法是看它们的内存地址是否相等。例如:
C& C::operator=(const C& rhs)
{
if (this==&rhs)
{
return *this;
}
}
这对许多程序而言都足够了。
Effective C++ 重要条款的更多相关文章
- 《MORE EFFECTIVE C++》条款20 条款21
条款20 协助编译器实现返回值优化 当重载运算符的时候,比如+ - * / 这类运算符,该函数返回的值一定是个右值(即不能是引用),那么执行一次运算的开销可能会在临时对象上调用多次构造函数和析构函数, ...
- 《More Effective C++》 条款5 谨慎定义类型转换函数
---恢复内容开始--- C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),它继承了C语言的转换方法,例如允许把char隐式转换为int和从short隐式转换 ...
- 《Effective C++》条款26 防卫潜伏的ambiguity模棱两可的状态
每个人都有思想.有些人相信自由经济学,有些人相信来生.有些人甚至相信COBOL是一种真正的程序设计语言.C++也有一种思想:它认为潜在的二义性不是一种错误.ambiguity 这是潜在二义性的一个例子 ...
- 《Effective C++》条款14 总是让base class拥有virtual destructor
有时,一个类想跟踪它有多少个对象存在.一个简单的方法是创建一个静态类成员来统计对象的个数.这个成员被初始化为0,在构造函数里加1,析构函数里减1.(条款m26里说明了如何把这种方法封装起来以便很容易地 ...
- Effective C++:条款37:绝不又一次定义继承而来的缺省參数值
因为又一次定义继承而来的non-virtual函数是不对的(见上一个条款),所以这个条款就将问题局限于:绝不又一次定义继承一个带有缺省參数值的virtual函数. (一) virtual函数是动态绑定 ...
- Effective C++:条款28:避免返回 handles 指向对象内部成员
(一) 有时候为了让一个对象尽量小,能够把数据放在另外一个辅助的struct中,然后再让一个类去指向它.看以下的代码: class Point { public: Point(int x, int y ...
- Effective C++:条款25:考虑写出一个不抛异常的swap函数
(一) 缺省情况下swap动作可由标准程序库提供的swap算法完毕: namespace std { template<typename T> void swap(T& a, T& ...
- Effective C++:条款14:在中小企业资源管理copying表现
(一) 在一项条款说法auto_ptr和tr1::share_ptr适合heap-based资源.然而,并非所有的资源都heap-based的.换句话说不tr1::shared_ptr 和 auto_ ...
- More Effective C++ 35 条款
一.基础议题(basics) 条款1:仔细区别 pointers 和 references(Distinguish between pointers and references) 一个基本的语法问题 ...
- Effective C++ 50条款
条款1:尽量用const和inline而不用#define 以const 行使常量折叠,用inline 代替常用操作的宏定义,而且库里面有很多常用函数可用.当然不能抛弃宏,宏还是很有用滴.偶最近才发现 ...
随机推荐
- JAVA 编程思想二
1: java 单根继承的优点? 方便垃圾回收: 垃圾回收的设计会方便实现. 多重继承的函数重名的问题. 2: 向下转型和向上转型? 向下转型不安全,向上转型安全. 3: system.g ...
- docker 学习(一)什么是Docker
项目中用到docker,就学习一下.第一篇是介绍. Sandboxie(沙箱):一个虚拟系统程序,允许你在沙盘环境中运行浏览器或其他程序,因此运行所产生的变化可以随后删除.它创造了一个类似沙盒的独立作 ...
- WPF win7+vs2010开发的打印功能,怎么在XP系统上无法打印
在wpf 中打印功能很强大,但最近是在win7上可以但是布置到xp上就不可以了,查了好多资料终于知道怎么回事了原来xp里没有.net framework3.5 安装一个就OK了要先安装4.0.
- Oracle数据去重
一.完全重复数据去重方法 具体思路是,首先创建一个临时表,然后将DISTINCT之后的表数据插入到这个临时表中;然后清空原表数据;再讲临时表中的数据插入到原表中;最后删除临时表. 对于表中完全重 ...
- .Net锦囊-C#,.Net发送邮件三种方法…
最近公司由于一个R&I项目的需要,用户要求在购买产品或出货等一些环节,需要发送邮件提醒或者说每周一让系统自动采集数据发送一封E-mail,因此我也就找来相关资料,写了一个Demo分享给大家,大 ...
- Umbraco back office 登录不了,如何解决
通过设置User的默认密码为"default", 它的Hash值为 bnWxWyFdCueCcKrqniYK9iAS+7E= 所以在SQL Server中执行以下脚本 UPDATE ...
- php array数组(第一部分)
创建一个数组 <?php $arr = array("My","name","is","zhangsan"); e ...
- yzm10的ACM集训小感
7月30号,ACM集训进行了两周,一切都已on the right way.这时的我适时地从题海中探出头,其实除了刷题,也该写点什么来总结下过去.首先,在第一周里,我学习了数据结构,知道了STL这么一 ...
- 仿iPhone、iPad界面滑屏切换
<!DOCTYPE html> <html lange='en'> <head> <meta charset='UTF-8'> <title> ...
- 剑指Offer的学习笔记(C#篇)-- 二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...