指针列表初始化和释放内存

时间:2015-09-15 21:11:23

标签: c++ pointers memory memory-management linked-list

使用list时,管理内存的好习惯是什么,

动态分配和释放(免费)我们不再需要它了。为了保持程序轻松并避免内存泄漏,请确保良好的内存管理(现在这是一个广泛的问题)

  1. 如何使用N个项初始化指向对象的指针列表?我应该使用new new来分配内存吗?
  2. 如果我想从列表和程序存储空间中完全删除一个项目,我应该使用pop还是删除或删除?差异?
  3. 我应该在迭代列表或.erase时使用operator delete。删除是否足以释放空间?
  4. pd.DataFrame([(15932, 2.9, 1), (15430, 3.6, 0), (16712, 10.9, 1), (15890, 6.6, 1)])
    
           0     1  2
    0  15932   2.9  1
    1  15430   3.6  0
    2  16712  10.9  1
    3  15890   6.6  1
    

3 个答案:

答案 0 :(得分:1)

C ++具有价值语义。列表拥有其上的对象。无论是int(内置类型),std::string(库类型)还是myclass(您的)列表,都是如此。确保您的课程可以被复制(或至少移动,但这是一个高级主题)。还要确保您的类析构函数正常工作,因为list::clear将调用它。

最初不要尝试使用指针列表。执行此操作时,请使用智能指针列表,但这已经是一个高级主题。应该完全避免使用“哑”指针列表。

答案 1 :(得分:1)

  
      
  1. 如何使用N个项初始化指向对象的指针列表?我应该使用new new来分配内存吗?
  2.   

别。让列表处理分配和释放。

lst.push_back(myclass());

如果您有许多项目要进入列表,您可以利用初始化程序。下面使用myclass构造函数,它以字符串和int为例。

list<myclass> lst {{"one", 1},{"two", 2},{"three", 3}};

如果这是一个需要使用指针的赋值,那么肯定使用new而不是malloc和它的家族来分配存储空间,但请考虑这是最后的手段。

首选使用智能指针。其中最重要的两个是unique_ptrshared_ptr

list<unique_ptr<myclass>> lst;

lst.push_back(unique_ptr<myclass>(new myclass()));

或在C ++ 14或更新版本中,

lst.push_back(make_unique<myclass>());

从列表中删除时,unique_ptr会自动销毁myclass。

但是我认为直接包含myclass的列表没有优势,除非myclass是类层次结构的基类。如果您处于学习C ++的早期阶段,请在进行此路由之前先阅读和练习基础知识。

list<shared_ptr<myclass>> lst;

lst.push_back(shared_ptr<myclass>(new myclass()));

制作一个可以与他人共享的引用计数我的课程。当每个用户都处理了他们的shared_ptr时,myclass将被销毁。这对于具有回调的系统非常有用。当回调触发时,回调对象将在那里,防止各种有趣的段错误。缺点是物体的寿命模糊。它被销毁时取决于未完成的shared_ptrs。

不允许使用shared_ptrs的循环引用,因为引用计数永远不会降为零。可能会有一些非常偷偷摸摸的代码来帮助这里,但我不会指望它。反正糟糕的程序设计。

new的原始指针。只是不要这样做。你有更好,更安全的选择。

lst.push_back(new myclass());
  
      
  1. 如果我想从列表和程序存储空间中完全删除一个项目,我应该使用pop还是删除或删除?差异?
  2.   
列表中不存在

remove。弹出,取决于您使用哪一个,删除firstlast元素。如果列表表示队列或堆栈,请使用pop。 erase可以删除任何元素,只要你知道它在哪里。找到它可能需要搜索。

使用存储的对象list<myclass>,您可能无法获得任何内存。该列表可以保存分配的RAM,因此以后不必再次请求它。坦率地说,我不确定标准的列表政策是什么。对于vector s,对象被销毁,但除非您手动强制调整大小,否则空间将保持分配状态。我相信列表的行为方式相同,因为resize方法的存在和文档的措辞。

如果你有一个原始指针,你必须delete它,然后从列表中删除它。您不能以其他顺序执行此操作,因为一旦从列表中删除指针就无法访问,并且RAM丢失给您。是的,你可以复制指针,然后将其从列表中删除,然后删除副本,但为什么要付出额外的努力呢?我相信指针仍将在列表中分配,但将无法访问并等待重用。

如果您使用unique_ptr,unique_ptr会为您处理。使用shared_ptr,您也可以处理,但您不一定知道何时处理。可能存在shared_ptr的另一个副本,阻止破坏。

  
      
  1. 我应该在迭代列表或.erase时使用operator delete。删除是否足以释放空间?
  2.   

在我的回答中覆盖2.使用指针,从列表中删除只删除指向myclass的指针,并且没有指向myclass的指针并且RAM丢失。使用智能指针,智能指针会破坏myclass,无需进一步的操作。

但如果列表保留了重新使用的RAM,则可能无法获得任何明显的RAM。

答案 2 :(得分:0)

虽然我认为你应该听别人说的话,但我想我仍然会回答你的问题所以你知道答案,你需要了解它们。智能指针当然最好用,但当我学习C ++指针时,我最初使用new / delete,我觉得它比直接使用智能指针更能让你理解(我知道你说你不知道他们是什么,所以他们只是为你管理记忆。)

  

如何使用N个项初始化指向对象的指针列表?我应该使用new new来分配内存吗?

正如您所做的那样,list<myclass *> lst (5)可以很好地制作指针列表,是的,您应该为列表中的每个元素使用new,以便在那里分配内存。例如,

list<myclass*>::iterator it = lst.begin();
*it = new myclass();
  

如果我想从列表和程序存储空间中完全删除一个项目,我应该使用pop还是删除或删除?差异?

要删除列表中的元素,您可以使用此处的列表删除功能:http://www.cplusplus.com/reference/list/list/erase/ 这将从列表中删除元素,但是如果使用指针则要小心,因为在删除此节点之前,您需要确保释放列表节点所持有的指针(见下文)

  

我应该在迭代列表或.erase时使用operator delete。删除是否足以释放空间?

.erase将从列表中删除该元素,但它不会为您释放指针,您将明确需要执行此类操作。

list<myclass*> lst(5);
list<myclass*>::iterator it = lst.begin();
*it = new myclass();
// and when you're ready to delete a node
if(*it != NULL)
     delete *it;
     lst.erase(it);

此外,在for循环中,请务必像我一样检查指针是否为NULL,然后再删除它。这可能是您在删除调用时出错的原因。由于不允许将内存存储为NULL,因此显然不允许删除那里的内存。这会给你一个分段错误。在删除之前检查NULL总是好的,以防万一除非你肯定会保留数据。

希望这会有所帮助。使用较新版本的C ++并不是最好的方法,但它应该按照你的问题回答你的问题。