两相结构具有以下形状:
struct something { something () : p1(NULL),p2(NULL) { } ~something () { if (p1) delete p1; if (p2) delete p2; } void initialize () { p1 = new int(2); p2 = new int(5); // May throw if allocation fails! } int* p1; int* p2; };
其中一个天真的构造函数(不注意分配失败)将泄漏内存:从不调用部分构造的对象的析构函数.
我的问题:以下代码是安全的,并且通过证据,智能指针是否可以避免两阶段构造?
struct something { something () : p1(new int(2)),p2(new int(5)) { } std::unique_ptr<int> p1; std::unique_ptr<int> p2; };
解决方法
是的,你的新代码很好.但请注意,在更复杂的情况下可能会有微妙的情况:
#include <memory> struct foo { foo(std::shared_ptr<int> a,std::shared_ptr<int> b) { } }; struct bar { foo f; bar() : f(std::shared_ptr<int>(new int),std::shared_ptr<int>(new int)) { } }; int main() { bar b; }
但是不安全,因为未指定在bar的初始化列表中评估foo的构造函数的参数的顺序.符合标准的编译器可能会选择执行深度或广度的第一个评估顺序(或其他任何东西,只要它们最终都被正确评估).这意味着如果第一个新int成功,但第二个新int在构造shared_ptr对象之前抛出,则第一个要执行的分配仍然可能泄漏.
如果您发现自己想要这样做,除了回到两阶段构造之外还有两种可能的解决方案:第一种可能是重构,第二种是在f之前首先单独构造shared_ptrs作为bar的成员.其中哪一项最合适的是我认为需要根据具体情况进行判断.
原文地址:https://www.jb51.cc/c/111369.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。