学习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++ 重要条款的更多相关文章

  1. 《MORE EFFECTIVE C++》条款20 条款21

    条款20 协助编译器实现返回值优化 当重载运算符的时候,比如+ - * / 这类运算符,该函数返回的值一定是个右值(即不能是引用),那么执行一次运算的开销可能会在临时对象上调用多次构造函数和析构函数, ...

  2. 《More Effective C++》 条款5 谨慎定义类型转换函数

    ---恢复内容开始--- C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),它继承了C语言的转换方法,例如允许把char隐式转换为int和从short隐式转换 ...

  3. 《Effective C++》条款26 防卫潜伏的ambiguity模棱两可的状态

    每个人都有思想.有些人相信自由经济学,有些人相信来生.有些人甚至相信COBOL是一种真正的程序设计语言.C++也有一种思想:它认为潜在的二义性不是一种错误.ambiguity 这是潜在二义性的一个例子 ...

  4. 《Effective C++》条款14 总是让base class拥有virtual destructor

    有时,一个类想跟踪它有多少个对象存在.一个简单的方法是创建一个静态类成员来统计对象的个数.这个成员被初始化为0,在构造函数里加1,析构函数里减1.(条款m26里说明了如何把这种方法封装起来以便很容易地 ...

  5. Effective C++:条款37:绝不又一次定义继承而来的缺省參数值

    因为又一次定义继承而来的non-virtual函数是不对的(见上一个条款),所以这个条款就将问题局限于:绝不又一次定义继承一个带有缺省參数值的virtual函数. (一) virtual函数是动态绑定 ...

  6. Effective C++:条款28:避免返回 handles 指向对象内部成员

    (一) 有时候为了让一个对象尽量小,能够把数据放在另外一个辅助的struct中,然后再让一个类去指向它.看以下的代码: class Point { public: Point(int x, int y ...

  7. Effective C++:条款25:考虑写出一个不抛异常的swap函数

    (一) 缺省情况下swap动作可由标准程序库提供的swap算法完毕: namespace std { template<typename T> void swap(T& a, T& ...

  8. Effective C++:条款14:在中小企业资源管理copying表现

    (一) 在一项条款说法auto_ptr和tr1::share_ptr适合heap-based资源.然而,并非所有的资源都heap-based的.换句话说不tr1::shared_ptr 和 auto_ ...

  9. More Effective C++ 35 条款

    一.基础议题(basics) 条款1:仔细区别 pointers 和 references(Distinguish between pointers and references) 一个基本的语法问题 ...

  10. Effective C++ 50条款

    条款1:尽量用const和inline而不用#define 以const 行使常量折叠,用inline 代替常用操作的宏定义,而且库里面有很多常用函数可用.当然不能抛弃宏,宏还是很有用滴.偶最近才发现 ...

随机推荐

  1. JAVA之BigInteger(转)【转】【很好用啊】

    用Java来处理高精度问题,相信对很多ACMer来说都是一件很happy的事,简单易懂.用Java刷了一些题,感觉Java还不错,在处理高精度和进制转换中,调用库函数的来处理.下面是写的一些Java中 ...

  2. 3-C++程序的结构1.5

    多文件结构和编译预处理命令 1.c++程序的一般组织结构 通常一个项目至少划分为三个文件:类定义文件(*.h文件).类实现文件(*.cpp文件)和类的使用文件(*.cpp,主函数文件).如下: 这三个 ...

  3. 建立JNI层的本地对象,并与JAVA层交互方法

    最近在做OpenCV4Android开发的时候,需要从摄像头捕获多个图片,传值给本地对象,每次捕获到图片都更新数据,最后将计算得到的数据传给JAVA层,并在界面中显示.经过摸索和调试后,找到了通过本地 ...

  4. SQL 分组获取产品 前两条记录

    select * from ( select *, ROW_NUMBER() over(partition by IPAddress order by recordtime desc) as rowN ...

  5. 用VisualSVN Server创建版本库,以及TortoiseSVN的使用

    介绍了VisualSVN Server和TortoiseSVN的下载,安装,汉化. SVN服务器搭建和使用(一) Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. ...

  6. python + requests实现的接口自动化框架详细教程

    前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自 ...

  7. 洛谷 - P3952 - 时间复杂度 - 模拟

    https://www.luogu.org/problemnew/show/P3952 这个模拟,注意每次进入循环的时候把新状态全部入栈,退出循环的时候就退栈. 第一次就错在发现ERR退出太及时,把剩 ...

  8. C#中Obsolete特性

    一般在逼格比较高的程序员代码中常见此特性手法,他们因为某些原因不详注释掉原有的代码,用Obsolete [csharp] view plain copy class Program { static  ...

  9. mysql 快速导入大SQL文件

    进入mysql mysql -u root -p 创建数据库 CREATE DATABASE 数据库名; 设置参数 set sql_log_bin=OFF;//关闭日志 ;//关闭autocommit ...

  10. 洛谷P2950 [USACO09OPEN]牛绣Bovine Embroidery

    P2950 [USACO09OPEN]牛绣Bovine Embroidery 题目描述 Bessie has taken up the detailed art of bovine embroider ...