「编程模型」C++ 资源引用
引子
把资源的申请和释放封装到类的构造函数和析构函数中后,调用者的逻辑表达清晰了,但安全性还得程序员手工管理,主要是通过硬编码来控制作用域,尤其要仔细处理异常抛出的情况。
处理一般的场景,用上面的方法就足够了,再增加抽象,就会是「杀鸡用牛刀」了。但真碰到需要「庖丁解牛」的复杂场景,就不能手工硬编码了,可以从下面 2 个方面来辅助理解这个转变:
其一,解决场景问题仍是最主要的,由规模大导致的复杂度,不能影响解决问题本身,这块额外多出的复杂度可以外包给「领域专家」来解决;
其二,可以类比手工作坊和工厂作业,规模大了必须要引入流水线、自动化这类的技术来使整个流程可控。
要操作的资源数量多了之后,最复杂的问题就是资源之间有依赖关系,比如:
依赖关系会调整,这时就容易引发安全问题,增加变更成本;
依赖的范围也多样,有局部的,也有全局的,处理方式也不尽相同。
这种情况下,手工编码维护依赖关系,已不是明智之举。
场景
C/C++ 是提供「指针」这种方式来解决这类问题的,「指针」在表达方面没什么问题,强大而灵活;但如果要正确处理依赖复杂性导致的安全性问题,难免会出现需要手动处理的特殊情况。
代码可以粘贴到https://wandbox.org 在线运行:
以上代码只是示意下使用场景,实际项目中的情况会比这个复杂,以至于有可能全部变为手动管理。
解决方案
为了彻底解决这种情况,C++ 把这个问题外包给了领域专家「智能指针(std::shared_ptr)」,这样调用者可以放心地使用「指针」来表达一切,而无需当心复杂度增加导致的其他问题。
代码可以粘贴到https://wandbox.org 在线运行:
如上,使用「智能指针」一切又回到了美好的样子。
C++ 推荐使用「std::make_shared」来构造「std::shared_ptr」,当然是有其充分理由的,如果不想了解具体细节,可以无脑使用:即使用「std::make_shared」来代替 「new」,使用「std::shared_ptr」来代替「*」,代码 Review 时,不能再出现 new 和 *。
如果有兴趣了解细节,可以搜索「c++ make_shared silver bullet」或中文「c++ make_shared 好处」等关键字。
版权声明: 本文为 InfoQ 作者【顿晓】的原创文章。
原文链接:【http://xie.infoq.cn/article/fa66df0680b54fd550bfb8f51】。文章转载请联系作者。
评论