条款13:用对象来管理资源
auto_ptr:(已经过时)
现在使用sharedptr、weakptr
条款14:RAII对象的拷贝行为
1、RAII
RAII,即resource acquisition is initialization,是管理资源、避免内存泄漏等方法,它保证在任何情况下,使用对象时先构造对象,后析构对象。
2、RAII对象的拷贝行为
- std::unique_ptr禁止拷贝,移动管理资源的所有权
- std::mutex既不可以拷贝也不可以移动
- std::shared_ptr管理资源的引用计数(拷贝时对引用+1)
- std::string拷贝底层资源,深拷贝
条款15:资源管理类中提供对原始资源的访问
条款16:new和delete要使用相同形式
1、释放数组要用delete[]
string* str1 = new std::string;
string* str2 = new std::string[100];
delete str1;
delete[] str2;
在内存中,数组是这样存储的:
如果使用的是delete[],系统会将指针向前移动8个字节,然后依次调用后面n个string类型的析构函数,最后将所有的空间都释放掉。
2、如果使用typedef也要注意delete的类型
typedef std::string AddressLines[4];
std::string *pal = new AddressLines; // new string[4]
delete[] pal;
条款17:以独立语句将newed对象置入智能指针
// define
int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);
// use it
processWidget(std::shared_ptr<Widget>(new Widget), priority());
上面这种传入参数的方式在不同编译器下的行为不确定,可能会导致内存泄漏,如:系统先调用new Widget创建一个对象,再调用priority函数,如果这个时候产生了异常,将导致Widget的内存泄漏。
应改为:
std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
现在基本使用make_shared来创建智能指针
条款18:让借口正确使用,不易被误用
1、新的类型预防错误的调用
2、自定义类型尽可能与内建类型行为一致
If(a * b = c)
如果abc都是整形,上面的语句将会报错;但是如果是自定义的类型,a * b将会返回一个值,如果这个值没有用const修饰,这个句子反而合法。
In fact, this is just a manifestation of another general guideline for making types easy to use correctly and hard to use incorrectly:unless there’s a good reason not to, have your types behave consistently with the built-in types. Clients already know how types like int behave, so you should strive to have your types behave the same way whenever reasonable.
3、使用智能指针
std::shared_ptr<Investment> createInvestment();
当引用计数变成0时,对象将自动被销毁。
On many platforms, such cross-DLL new/delete pairs lead to runtime errors, std::shared_ptr avoids the problem, because its default deleted uses delete from the same DLL where the std::shared_ptr is create.