条款13:以对象管理资源
会因为各种各样的原因delete没有被执行:过早的return goto、异常抛出
把资源(例如内存)管理放在对象内,就可以在析构函数时执行
利用析构函数确保资源被释放。
auto_ptr<Obj> p1(new Obj());
auto_ptr<Obj> p2(p1); 这时候p2指向对象,p1为NULL
p1 = p2; 这时候p1指向对象,p2为NULL
tr1的shared_ptr
auto_ptr只在析构函数中作delete,而不是delete[]
条款14:在资源管理类中小心copy行为
条款15:在资源管理类中提供对原始资源的访问
条款16:成对的new、delete要有相同的形式
调用new:
1:分配内存
2:调用构造函数(一个或多个)
调用delete:
1:调用析构函数
2:释放内存
被释放的内存区域,有多少个对象就调用多少次析构函数
对于对象数组,不少编译器会有一个记录,来说明对象的个数
int *p = new int;
如果调用:
delete[]p;
结果未定义,编译器会将其解释为一个数组
typedef std::string AddressLine[4];
std::string * pal = new AddressLine;
如果要删除:
delete pal; 未定义!!!
delete [] pal; 正确
尽量不要对数组用typedef
条款17:以独立的语句将newed对象置入智能指针中
如果执行次序不可控,可能导致内存泄露
要确保将指针放入智能指针内!
条款18:让接口容易被使用
要开发一个接口,首先要考虑客户可能会出什么样的错误。
每个接口在使用的时候,都会有假设、前提条件,因此在接口内部要测试这些假设是否成立!!!
尽量与内置类型提供一致的接口
如果返回的是指针,将其放入只能智能指针里,将内存释放的任务交给智能指针
条款19:设计class如设计type
1:新类型如何被创建
构造函数、析构函数、newnew[] delete delete[]
2:对象的初始化和对象的赋值有何差别
构造函数、拷贝构造函数、拷贝赋值函数
3:新类型如果被传值pass byvalue,如何?
4:新类型的合法值
合法性检查
5:考虑继承关系
如果继承于父类,受到virtualnon-virtual函数的影响
如果被继承,考虑析构函数是否为virtual
6:新类型需要什么样的转换
是否允许类型的隐式转换:如果希望T1被隐式转换为T2,必须在T1中写一个类型转换函数(operatorT2),或者在T2中实现一个非explicit的单参数构造函数
7:什么样的操作符和函数对其是合理的
8:什么样的标准函数应该被禁止(设置为private)
9:谁该取用它的成员
决定哪些成员是public、protected、private,或者哪些class、function是friend
10:什么是它的“未声明接口”?
11:是否需要将class定义为template
12:是否真的需要一个新类型
条款20:以传const 引用来代替传值
const Obj& rhs
参数和返回值,默认都是传值类型
Class Person
{
Public:
Person();
Virtual ~Person();
…
Private:
String name;
String address;
};
Class Student: public Person
{
Public:
Student();
~Student();
…
Private:
String schoolName;
String schoolAddress;
};
Bool validateStudent(Student s);
Student sto;
Bool bOK = validtatestudent(sto);
调用student的拷贝构造函数,调用Person的拷贝构造函数(调用Person内两个string的构造函数),
调用student内两个string的构造函数。
传递reference可以防止对象的切割
传入的reference,底层转化为指针
尽量传引用。处理内置类型(int、char…)STL的迭代器和函数对象。