【问题标题】:How to free memory in my Class destructor?如何在我的类析构函数中释放内存?
【发布时间】:2013-01-04 05:50:39
【问题描述】:

好的,我想这个问题听起来可能太傻了,但是内存管理(尤其是在 C/C++ 中)从来都不是我的强项,而且由于它通常不是一件引人注目的事情,所以我倾向于忽略它。所以,如果这一切听起来很愚蠢,请原谅我。然而,由于我目前的项目涉及大量数据和处理,内存消耗很容易在几秒钟内超过 2GB,这肯定会减慢整个过程,所以......是时候开始思考了解决方法。


所以,这是我的情况……

我的主体类(我正在创建数百万个实例(希望它们会自动删除,因为它们不再被使用),所以应该 this 是罪魁祸首)是(大致)这个:

class MyClass
{
    public:
        // My Constructors
        MyClass ();
        MyClass (std::string param);

        // My Destructor (still empty)
        virtual ~MyClass ();

        // Some methods
        void methodA(std::string moves);
        void methodB();

        //----------------------
        // My Variables
        //----------------------
        boost::array<int,64> arrA;
        boost::array<unsigned int,13> arrB;
        unsigned int key;

        boost::array<int,3> arrC;       
        int argA;
        int argB;
};

这是(大致 - 实际代码已被更改)上述类的实例是如何创建的:

vector<MyClass*> SomeOtherClass::getListOfObjects()
{   
    vector<MyClass*> objects;

    for (int i=0; i<MAX_OBJS; i++)
    {
          // Do some preparatory work
          objects += new MyClass();
    }

    return objects;
}

下面是如何使用上述函数的结果:

void SomeOtherClass::doSth()
{
    vector<MyClass*> objs = this->getListOfObjects();
    int objsSize = objs.size();

    for (int i=0; i<objsSize; i++)
    {
        MyClass* obj = objs[i];

        // Do sth with obj

        delete objs[i];
    }
}

所以,我的问题是:

  • 我应该在我的析构函数中做什么,以便当不再需要对象并因此被释放时,它的所有“子组件”也会被释放? (例如 2 个boost::arrays)

  • 您注意到上述方法有什么问题吗?


如果您对我的实现还有其他需要了解的信息,请告诉我...

【问题讨论】:

  • "it's usually not a noticeable thing, I tend to overlook it." -- 有史以来最糟糕的态度。您熟悉delete 关键字吗?
  • 你缺少复制/移动构造函数
  • 您的班级没有要管理的内存。你在制作这些MyClass 对象中的多少?
  • @Dr.Kameleon:我认为当前硬件上的任何当前内存分配器都无法达到这样的速度。更不用说这个对象至少有 336 个字节,所以 1 亿个是 33.6 GB,这不适合当今普通计算机上的内存。
  • 您可能不需要指针向量(使用 vector&lt;MyClass&gt; 代替),只是要小心,因为要复制的内容要多得多(通过引用传递它 getListOfObjects 而不是返回它,这在任何一种情况下都可能是个好主意)。

标签: c++ arrays memory-management boost destructor


【解决方案1】:

你的类成员看起来不是动态分配的,在这种情况下你不需要在析构函数中显式地delete 任何东西。如果你碰巧遗漏了一些指向已分配内存的指针,在这个问题中,你用new分配,你需要在析构函数中delete这些。

请记住,如果您使用new,则需要delete,与new[]-delete[] 类似。除非分配给std::unique_ptr的情况。

如果您的 MyClass 对象本身使用 new 在堆上分配,那么您将不得不 delete 它们。

附言如果您使用的是 C++11,您现在应该使用 std::array


从您的新代码中,很明显,无论谁保留从getListOfObjects() 返回的列表,都需要在每个元素被销毁时调用delete。很可能是SomeOtherClass的析构函数。

或者,您可以将 MyClass* 指针包装在 std::unique_ptrstd::shared_ptr (或任何可能与此处相关的 boost 智能指针)中,然后当持有它们的向量超出范围和被销毁了。


如果doSth 的表示是准确的,并确保MyClass 的所有实例都得到deleted,那么从内存泄漏的角度来看,这段代码似乎没问题。

【讨论】:

  • 嗯...我明白你的意思了。也许,你是对的。给我一点时间来测试一下。
  • 我假设你可以知道它们是动态分配的,因为类成员将是指针,对吗?
  • @SebbyJohanns 是的,这就是我使用的......让我添加警告
  • @SebbyJohanns 指针数据成员并不意味着动态分配。您必须检查这些指针是否指向使用newnew[] 动态分配的一些内存。即便如此,也不是 100% 清楚谁负责调用删除。在这些情况下最好避免使用原始指针并使用适当的智能指针。
  • @Dr.Kameleon 您可能想要编辑问题以显示分配和解除分配对象的代码以及向量的定义,并在那里添加这些详细信息
【解决方案2】:

我所看到的只是一个正确管理它的内存的类。 boost::array 是对普通旧数组的精美包装(boost::array&lt;int,64&gt; arrA 只是 int arrA[64] 添加了方法以使其成为标准库算法的随机访问只读集合),因此被分配为对象的一部分。

现在如果你说你有泄漏,你显然在某处内存管理不善,但它不在这里。


在现代 C++ 中,趋势是避免自己编写删除操作,而是将其留给专门的析构函数。鉴于上面的分配代码,Boost.Pointer Container 可能是正确的工具。

【讨论】:

    【解决方案3】:

    这听起来有点奇怪

    我的主要类(我正在创建数百万个实例 (希望被自动删除,因为它们不再被 使用)

    如果您正在创建 MyClass 的实例并且没有使用某种智能指针完成它,那么它们不会被神奇地删除,您需要完成这项工作。

    【讨论】:

      【解决方案4】:

      我看到的都是在堆栈上分配的。因此它们在析构函数中得到妥善管理和删除。如果存在内存泄漏,可能是您正在调用 new MyClass 但没有释放它们。或其他地方。

      正如我在编辑的代码中看到的那样,有一个向量您是否正在删除 SomeOtherClass::getListOfObjects 返回的 objects 的项目?

      您也可以使用boost::shared_ptr&lt;MyClass&gt; 代替原始指针MyClass*

      【讨论】:

      • “我看到的都是在堆栈上分配的” - 不正确...成员将嵌入到创建对象的位置,可以是静态的,在堆栈上或堆上。关键点是,无论对对象应用什么内存管理都会自动处理成员......这就是你正确警告new Myclass sans release 的地方。
      猜你喜欢
      • 1970-01-01
      • 2016-10-25
      • 1970-01-01
      • 2017-08-19
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-12
      • 2019-04-27
      相关资源
      最近更新 更多