将指针赋值给指针(以及将指针传递给类)时使用delete的混淆

  • 本文关键字:指针 delete 赋值 c++
  • 更新时间 :
  • 英文 :


抱歉,如果我的最后一个问题是非常相似的,但我有另一个查询何时以及如果我应该使用delete关键字。

示例代码。

初始化一个类,它的实参是指向vector的指针。这些对象从堆中分配内存。然后,我将这些对象传递给我的类构造函数,它也从堆中分配内存。

代码如下:在main函数

     //This will also change each loop
     vector<A*>* ex1 = new vector<A*>;
     vector<B*>* ex2 = new vector<B*>;         
     vector<C*>* ex3 = new vector<B*>;
     for(int i =0; i < 10; i++){
       ex1->push_back( new A(i); );
       ex2->push_back( new B(i); );
       ex3->push_back( new C(i); );
     }

     MainClass* ex_main = new MainClass(ex1,ex2,ex3);
在MainClass.cxx

   MainClass::MainClass(vector<A*>* ex_A, vector<B*>* ex_B, vector<C*>* ex_C): m_ex_A(ex_A), m_ex_B(ex_B), m_ex_C(ex_C) {}
在MainClass.h

   vector<A*>* m_ex_A;
   vector<B*>* m_ex_B;         
   vector<C*>* m_ex_C;

m_ex1、m_ex2和m_ex3已被赋值给堆栈,但已被赋值给指针指向向量的指针。

问题。

我删除m_ex_A,B和C在类MainClass的析析函数(我知道我将需要删除每个向量中的元素),也指针指向向量的指针在主函数?

e.x。在MainClass的析构函数中(我做了一些比这更通用的事情,但这更容易显示)

for(int i = 0; i < m_ex_A->size(); i++){
     delete m_ex_A->at(i);
 }
  delete m_ex_A;

然后,我将在main函数中对指向指针ex1, ex2, ex3的向量的指针采取类似的方法,并删除main类。

我的困惑来自m_ex_A,B和C被分配给堆栈,而不是动态的,但他们被分配给动态对象的事实?

我的猜测是使用删除m_ex_A,B, C对象,因为我已经动态初始化他们?

还有什么更有效的使用堆内存或堆栈?

我想我可能使用了太多的动态内存

您一定应该在某处删除动态分配的对象。也可以在MainClass的析构函数中这样做,但我个人认为这是一种糟糕的风格。为什么?因为你在不同的地方,不同的实体中进行分配和删除。事实上,你正在转移这些对象的所有权,所以你应该非常小心,不要删除两次之类的。我宁愿使用shared_ptrunique_ptr,这样我就可以从所有这些微观管理中解脱出来。你可以在网上搜索它们,它们非常容易使用。

至于第二个问题——你必须只删除每个对象一次。复制指针并不会创建新对象,它只是指向同一个对象的另一个指针。

这不是对问题的直接回答,而是试图澄清潜在的问题:

概念上的问题是原始的指针不传递(更糟糕的是没有办法)所有权信息。它们只是一个指向内存位置的指针。

现在,无论何时使用new分配动态内存,您都有责任在某处删除它。决定它的位置是设计程序的一部分。如果你传递一个指针给某个对象,就像在你的例子中,你需要记录对象是否拥有指向内存的传递的所有权(在这种情况下,对象负责清理),或者如果它不(调用者仍然负责)。

使用原始指针,没有办法知道(除了文档或检查实现)任何给定的函数是否拥有所有权。

这就是新的c++ 11(也可以从boost中获得)智能指针(unique_ptrshared_ptr)适合的地方。它们立即传达谁负责删除内存,甚至更好地自动处理(并且很少-或者在unique_ptr的情况下没有-开销)

所以作为最后的指导方针:永远不要使用原始指针而不是智能指针或其他类型的RAII机制!(直到您获得了更多使用这些方法的经验,并且能够证明在这种特殊情况下,原始指针实际上是更好的解决方案)

最新更新