【问题标题】:How does ptr_vector manage memory?ptr_vector 如何管理内存?
【发布时间】:2012-07-24 20:18:50
【问题描述】:

我目前正在学习 c++,以便使用 opengl 进行较低级别的编码。我来自一个沉重的 objc 背景,所以我对内存管理有一些了解,但我似乎无法理解“boost”库如何管理像 ptr_vector 这样的容器类型。

我认为我的问题与我不知道ptr_vector 如何管理自身及其对象的破坏有关。

请看下面的代码:

// Header file
...
ptr_vector<IObject3D> objects;
...

// Implementation file
...
void ApplicationEngine::init()
{
    WavefrontObject3D *object = new WavefrontObject3D("Ninja.obj");
    objects.push_back(object); 
}
...

那么,对于真正的问题:我是否通过“object”变量在此处创建了泄漏?

我习惯于在 objc 中通过显式调用手动保留和释放我的对象: 以前我必须 alloc init WavefrontObject3D object,将其添加到数组中,然后 release 同一个对象以避免泄漏。

但是当我在push_back 调用之后添加delete object 时,WavefrontObject3D 的解构函数object 被调用。这给了我一个提示,ptr_vector 没有保留object 变量。我的假设正确吗?

其他但相关的问题:假设我想销毁包含类 ApplicationEngine 我不必在 ptr_vector 或它管理的元素上调用某种解构器?

【问题讨论】:

  • But when I add a delete object after the push_back call the deconstructor of the WavefrontObject3D object is called. 这就是 delete 的用途。它在指针指向的实例上调用析构函数。
  • 我认为你应该阅读RAII,这是大多数内存管理在所谓的“现代”c++ 中完成的方式。
  • 伟大的资源@LucTouraille!正是我想要接近 C++ 的方式。

标签: c++ memory-management boost


【解决方案1】:

不,这不会造成泄漏。当容器超出范围时,所有ptr_* 容器都会删除存储在其中的对象。

如果您在将对象添加到容器后删除它,您将创建undefined behavior,因为容器将再次尝试删除它。

附加问题:否,如果您按值存储 ptr_vector,则其生命周期由周围类的范围管理。

让我们写一个ptr_vector 的简单实现。它不支持间接迭代器和自定义删除器以及许多其他东西,但显示了使用的原则。

template <typename T>
class ptr_vector {
public:
  // assume control over it
  void push_back(T* x) 
  { if(x) c_.push_back(x); else throw bad_pointer(); }

  ~ptr_vector() { 
    // delete everything that is stored here
    for(auto x : c_)  delete x;
  }
private:
  std::vector<T*> c_;
};


// a user class
struct user_class {
  void addSomething() { x.push_back(new int(23)); }
  ptr_vector<int> x;
};

如果用户类超出范围,ptr_vector 的析构函数将 被调用,所有内存都将被回收。看不到泄漏。

【讨论】:

    【解决方案2】:
    void push_back( T* x );
    

    要求:x != 0 效果:将指针插入容器并 获得它的所有权 抛出:bad_pointer if x == 0 异常安全: 强有力的保证

    template
        < 
            class T, 
            class CloneAllocator = heap_clone_allocator,
            class Allocator      = std::allocator<void*>
        >
        class ptr_vector : public ptr_sequence_adapter
                                  <
                                      T,
                                      std::vector<void*,Allocator>,
                                      CloneAllocator
                                  >
    

    因此您可以指定自己的CloneAllocator,而不是删除存储在ptr_vector 中的元素,但heap_clone_allocatorCloneAllocator 的默认值)会删除析构函数中存储的所有元素。

    http://www.boost.org/doc/libs/1_50_0/libs/ptr_container/doc/reference.html#class-heap-clone-allocator

    【讨论】:

      【解决方案3】:

      ptr_containers own the memory pointed at by the pointer you pass to it. 阅读the docs 了解有关可克隆概念的更多信息。

      【讨论】:

        【解决方案4】:

        ptr_vector 将释放其析构函数中的所有元素,因此您无需做任何比您已经做的事情更多的事情,即创建对象,将它们添加到ptr_vector,然后离开管理给它。显式调用delete 将使对象被销毁两次(一次是在您请求它时,一次是在ptr_vector 完成时)。换句话说,ptr_vector 不会复制对象。

        ApplicationEngine 完成时,如果它有ptr_vector 的实例,将调用该向量的析构函数,进而删除添加的对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多