Item13 以对象管理资源
资源:
考虑以下场景,delete都不会执行,资源都会泄漏,
class Investment {...}; // 投资行为的父类
Investment* creatInvestment(); // 创建对象的工厂
void f() {
Investment* pInv = creatInvestment();
// do_something
delete pInv;
}
解决思路,以对象管理资源:
上述函数可以使用智能指针的方式修改
#include <memory>
class Investment {};
Investment* creatInvestment() {
return new Investment;
}
void f() {
// std::auto_ptr<Investment> pInv(creatInvestment()); // c++98标准
std::shared_ptr<Investment> pInv(creatInvestment()); // c++11标准
}
/*
* auto_ptr 为了防止同一个对象被删除多次,通过拷贝和或者拷贝赋值,该指针会变为null
* 与stl容器要求的正常复制行为不兼容
* c++11 中unique_ptr会静止拷贝操作
int main() {
std::auto_ptr<Investment> pInv1(creatInvestment());
std::auto_ptr<Investment> pInv2(pInv1);
if (pInv1.get() == nullptr) std::cout << "pInv1 is null\n";
if (pInv2.get() != nullptr) std::cout << "pInv2 is not null\n";
return 0;
}
*/
注意事项:不能用来管理动态分配的数组,因为底层调用的时delete,而不是delete []
int main() {
std::shared_ptr<std::string> aps(new std::string[10]);
return 0;
}
/*
* 报错内容
munmap_chunk(): invalid pointer
Aborted (core dumped)
*/
考虑以下场景:
class Widget {};
int priority() {return 0;}
void processWidget(std::shared_ptr<Widget> pw, int priority) {}
int main() {
// processWidget(new Widget, priority()); // error: could not convert ‘(Widget*)operator new(1)’ from ‘Widget*’ to ‘std::shared_ptr<Widget>’
// processWidget(std::shared_ptr<Widget>(new Widget), priority());
// std::shared_ptr<Widget> pw(new Widget);
// processWidget(pw, priority());
processWidget(std::make_shared<Widget>(), priority());
return 0;
}
processWidget函数可能的执行顺序(取决于编译器,保证1在3前面,2的执行顺序不确定):
当调用?priority() 发生异常,new Widget 返回的指针将丢失,资源不能被正确释放
解决方案: