c – 智能指针是否排除了对两相构造的需求?

前端之家收集整理的这篇文章主要介绍了c – 智能指针是否排除了对两相构造的需求?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
两相结构具有以下形状:
  1. struct something {
  2. something ()
  3. : p1(NULL),p2(NULL)
  4. { }
  5.  
  6. ~something () {
  7. if (p1) delete p1;
  8. if (p2) delete p2;
  9. }
  10.  
  11. void initialize () {
  12. p1 = new int(2);
  13. p2 = new int(5); // May throw if allocation fails!
  14. }
  15.  
  16. int* p1;
  17. int* p2;
  18. };

其中一个天真的构造函数(不注意分配失败)将泄漏内存:从不调用部分构造的对象的析构函数.

我的问题:以下代码是安全的,并且通过证据,智能指针是否可以避免两阶段构造?

  1. struct something {
  2. something ()
  3. : p1(new int(2)),p2(new int(5))
  4. { }
  5.  
  6. std::unique_ptr<int> p1;
  7. std::unique_ptr<int> p2;
  8. };

解决方法

是的,你的新代码很好.但请注意,在更复杂的情况下可能会有微妙的情况:
  1. #include <memory>
  2.  
  3. struct foo {
  4. foo(std::shared_ptr<int> a,std::shared_ptr<int> b) { }
  5. };
  6.  
  7. struct bar {
  8. foo f;
  9. bar() : f(std::shared_ptr<int>(new int),std::shared_ptr<int>(new int)) { }
  10. };
  11.  
  12. int main() {
  13. bar b;
  14. }

但是不安全,因为未指定在bar的初始化列表中评估foo的构造函数的参数的顺序.符合标准的编译器可能会选择执行深度或广度的第一个评估顺序(或其他任何东西,只要它们最终都被正确评估).这意味着如果第一个新int成功,但第二个新int在构造shared_ptr对象之前抛出,则第一个要执行的分配仍然可能泄漏.

如果您发现自己想要这样做,除了回到两阶段构造之外还有两种可能的解决方案:第一种可能是重构,第二种是在f之前首先单独构造shared_ptrs作为bar的成员.其中哪一项最合适的是我认为需要根据具体情况进行判断.

猜你在找的C&C++相关文章