2010-10-18 104 views
1

我有一个方法创建了一些Foo并将它添加到Foos的矢量中。 Foos负责在销毁期间删除他们的酒吧。 Foo构造函数需要一个Bars的指针和它们的大小。当函数返回时,本地Foo被删除并销毁它的Bars,但是我得到一个有效的Foo对象。C++用局部变量指针管理

我应该如何更正确地处理这个问题?我应该用其他方式管理酒吧吗?我应该让构造函数复制数组吗?我可能会有成千上万的酒吧。

还没有试图编译这个,这只是一个发生了什么事情的例子。

class Bar 
{ 
    public: 
     Bar(){} 
     ~Bar(){} 

     int a; 
     int b; 
     int c; 
}; 

class Foo 
{ 
    private: 
     Bar * myBars; 
     int size; 

    public: 
     Foo(Bar * myBars, int size) 
     { 
      this->myBars = myBars; 
      this->size = size; 
     } 

     Bar * getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return size; 
     } 

     ~Foo() 
     { 
      if(myBars != NULL) 
      { 
       if(size == 1) 
       { 
        delete myBars; 
       } 
       else if(size > 1) 
       { 
        delete [] myBars; 
       } 
      } 
     } 
}; 

void doIt(std::vector<Foo> & foos) 
{ 
    Bar * myBars = new Bar[4]; 
    //Pretend we initialize the Bars... 
    Foo foo(myBars); 
    foos.push_back(foo); 

    //local foo gets deleted 
} 

int main() 
{ 
    std::vector<Foo> foos; 
    doIt(foos); 

    Bar * myBars = foos[0].getBars(); 
    int size = foos[0].getSize(); 

    //Do something with myBars 

    return 0; 
} 
+0

大小并不是一个很好的指示符,因为您可以像这个新的Bar [1]那样分配,而且必须使用delete []删除它,否则是否使用delete []或delete。因此,使用布尔值来指示数组分配,或者甚至更好地传递一个函数,它将执行正确的操作,或者使用知道如何删除它的智能指针。 – 2010-10-18 17:17:02

回答

0

类似酒吧,你可以创建富也反对在堆上,以避免在doIt方法functon破坏。如果Foo对象是动态分配的,它将不会在doIt()函数返回时被销毁。

您可以像下面(工作代码)结束清理所有Foo和Bar对象

#include <vector> 
using namespace std; 
class Bar 
{ 
    public: 
     Bar(){} 
     ~Bar(){} 

     int a; 
     int b; 
     int c; 
}; 

class Foo 
{ 
    private: 
     Bar * myBars; 
     int size; 

    public: 
     Foo(Bar * myBars, int size) 
     { 
      this->myBars = myBars; 
      this->size = size; 
     } 

     Bar * getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return size; 
     } 

     ~Foo() 
     { 
      if(myBars != NULL) 
      { 
       if(size == 1) 
       { 
        delete myBars; 
       } 
       else if(size > 1) 
       { 
        delete [] myBars; 
       } 
      } 
     } 
}; 

void doIt(std::vector<Foo *> & foos) 
{ 
    Bar * myBars = new Bar[4]; 
    //Pretend we initialize the Bars... 
    Foo *pFoo = new Foo(myBars, 4); 
    foos.push_back(pFoo); 
} 

int main() 
{ 
    std::vector<Foo *> foos; 
    doIt(foos); 

    Bar * myBars = foos[0]->getBars(); 
    int size = foos[0]->getSize(); 

    for(int i = 0;i < foos.size(); i++) 
    { 
     delete foos[i]; 
    } 
    foos.clear(); 

    return 0; 
} 
+0

我喜欢std :: auto_ptr,但它不适用于标准容器。此外,代码并不是特例安全的。如果你打算拥有一个拥有指针的容器,那么你应该看看boost指针容器。 boost :: ptr_vector 2010-10-18 16:25:15

+0

@Martin:已更新。 – bjskishore123 2010-10-18 16:28:41

1

为什么不使用std::vectorBar S:

class Foo 
{ 
    private: 
     vector<Bar> myBars; 

    public: 
     Foo(const vector<Bar>& bars) : myBars(bars) {} 

     vector<Bar>& getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return myBars.size(); 
     } 
}; 
+0

比我的好主意。我在想什么。 – 2010-10-18 20:20:47

+0

@马丁,谢谢。 – Donotalo 2010-10-19 01:51:53

0

你不显示拷贝构造函数,并且没有合适的默认拷贝构造函数。 您也没有stl容器经常需要的默认(无参数)构造函数。

当您将Foo推入矢量中时,它将创建一个新的Foo作为副本。

目前您可能会删除酒吧指针两次。

本机数组应避免使用非POD类型 - Bar[4]不会在每个对象的Bar上运行构造函数。优先使用Vector

+0

是的,它正在删除Bar指针两次。 – bjskishore123 2010-10-18 16:39:05

+0

我意识到发生了什么,我正在寻找最好的方法(tm)来解决它。 – foobar1234 2010-10-18 18:05:58

+1

@ foobar1234:推荐阅读一些书,比如Meyers Effective C++,Sutter Exceptional C++。没有关于所有Foo和Bar的总体结构和用法的更多细节,“最佳方式”(tm)将不清楚。例如,你会一直'为每个'的容器,或需要查找,需要添加和/或删除许多项目等。 – 2010-10-18 18:18:07