-
令人惊讶的是,即使我们使用对象管理资源,下面代码仍存在泄漏资源。
inline Resource* GetResource() { return new Resource(1); } inline void OtherProgress(std::shared_ptrResource, int Priority) {} inline void UseResource() { OtherProgress(std::shared_ptr (GetResource()), GetPriority(100)); } -
编译器在产出OtherProgress调用码之前,需要核算每一个被传递的实参。上述第二实参只是一个单纯的返回优先级函数,但是第一实参由两部分组成:
- 执行new Resource表达式
- 调用shared_ptr构造函数
这意味着在调用OtherProgress之前,要做这三件事。
但是编译器并不保证这三件事情的次序。这和其他语言如Java,C#不同,那两种语言总是以特定的次序完成函数的核算。如果编译器为了更高效的代码,那么它们的调用次序不一定是按实参的次序。可能:- 执行new Resource表达式
- 调用GetPriority函数
- 调用shared_ptr构造函数
假如是按这种方式,如果对调用GetPriority函数时出现异常,会发生什么事情,new Resource返回的资源尚未置入shared_ptr智能指针,也就是未进入我们防卫资源泄漏的武器。
这种由于核算实参次序导致的问题可以很简单的被避免:使用分离语句,先创建Resource,再调用OtherProgress。inline void OtherProgress(std::shared_ptr
Resource, int Priority) {} inline void UseResource() { const std::shared_ptr ResourcePointerOne(GetResource()); OtherProgress(ResourcePointerOne, 100); }
这样,编译器不能再重新排列这些跨语句的各项操作,从而促使事件向我们期望的方向发展。
二. 总结- 以独立语句将 newed 对象存储于(置入)智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏。



