删除C ++中静态函数中分配的内存

时间:2011-02-02 09:41:32

标签: c++

我有C ++类如下

class anotherClass;

class myClass {
   private:
    myClass() {}
    ~myClass() {}

    typedef std::map<string, anotherClass* > stringToClass;
        static stringToClass s_stringToClass;

    public:
         static anotherClass* getStringToclass(string name);

};
上面的getStringToClass定义中的

如下

anotherClass* myClass::getStringToClass(string name) {
     stringToClass::iterator iter;
     iter = s_stringToClass.find(name);

     if(iter == s_stringToClass.end()) {
          typedef stringToClass::value_type stringToClassPair;
          anotherClass* pothClass = new anotherClass();
          s_stringToClass.insert(stringToClassPair(name, pothClass));
          return pothClass;
     }
     else {
        return iter->second;
     }
}

现在我的问题是我们正在如上定义的静态函数中分配内存。我们怎样才能删除内存?我们可以在析构函数中删除内存,因为析构函数不是静态的吗?

感谢您的帮助。

6 个答案:

答案 0 :(得分:2)

该集合将自动清理,但其中的指针不会,所以你真的有两个选择:

  • 使用了一个将被清理的shared_ptr集合
  • 使用存储原始指针但清理它们的集合

后一种类型的类有提升但不确定它们有一个用于地图,我会选择前者。

我也会修改结构,以便不使用静态函数和静态映射,而是使用带有函数和映射的类,并且具有该类的静态(单例)实例。

您的函数也可能被修改为返回一个shared_ptr,但它仍然可以返回一个常规指针,因为该项目将永久保留在地图中,因此您无需担心它会失效。

因为它永远不会是NULL,你甚至可以返回一个引用。

   typedef std::map<string, boost::shared_ptr<anotherClass> > stringToClass;
   anotherClass& myClass::getStringToClass(string const& name)  
   {
       boost::shared_ptr<anotherClass> & value = s_stringToClass[name];
       if( !value )
       {
          value.reset( new anotherClass );
       }
       return *value;
   }

您也可以考虑将其设置为线程安全。

答案 1 :(得分:0)

我会使用某种智能指针,例如Boost提供的指针,而不是原始指针。

答案 2 :(得分:0)

是的,您可以在析构函数中删除静态变量。

话虽如此,这不是一个好主意。如果您有两个类的实例,使用静态变量,一个被销毁,该怎么办?它的析构函数会删除内存,导致类的剩余实例出现问题。

除了你对静态成员的奇怪使用外,使用智能指针会更明智。

答案 3 :(得分:0)

如果将它存储在一个静态变量中,我猜你需要它们直到你的进程执行结束......如果没有,那么你需要添加一个方法来清除这个静态变量,删除每个元素并调用当你不再需要它时。

您不应该在析构函数中执行此操作,因为静态变量未链接到您的类实例。

答案 4 :(得分:0)

问题一:

函数永远不会返回指针(除非你真的真的有) 在这种情况下,你没有。

返回的指针没有所有权语义,因此不清楚指针的所有者是谁(如果你不知道谁拥有指针那么你就不知道谁可以删除它了。)

因此要么返回引用,要么返回智能指针 在这种情况下参考。因为所有动态创建的对象都在本地维护。

因为你显然是新手。使用boost :: shared_pointer。从技术上讲,这可能不是这种情况下最好的一种,但它是学习时最容易使用的。我会看看其他可用的智能指针,并了解何时适合使用每一个。

class anotherClass;

class myClass 
{
   private:
     myClass() {}
    ~myClass() {}

     typedef boost::ptr_map<string, anotherClass > stringToClass;
                               //  ^^^ Note: Not std:: you are not allowed to add class to std::

    static stringToClass s_stringToClass;
    // Ownership now maintained by the map automatically.

    public:
         // Return a reference.
         // We retain ownership inside this class
         static anotherClass& getStringToclass(string name);

};

代码:

anotherClass& myClass::getStringToClass(string name)
{
     stringToClass::iterator iter;
     iter = s_stringToClass.find(name);

     if(iter == s_stringToClass.end())
     {
          s_stringToClass[name] = new anotherClass();
          return s_stringToClass[name];
     }
     else
     {
        return iter->second;
     }
}

答案 5 :(得分:0)

我认为在你的情况下,析构函数不会有帮助,因为没有MyClass的任何对象。

我提出三种方法
1.不存储指针,存储对象本身。
2.将删除功能放入atexit;在你的情况下

class MyClass
{
.....//Your already existing code
static void Destroy()
{
     //iterate s_StringToClass and delete them
}

static void getStringToClass( string name )
{
     struct DestroySetter
     { 
          DestroySetter()
          { 
               atexit( MyClass::Destroy );
          }
     };
     static DestroySetter setter; //Setup the destoyer
     //Your existing code here
}


3.使用智能指针管理资源,建议使用shared_ptr。
虽然我采取了第二种方式,但我建议采用第三种方式。