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

list of pointers initialize and release memory

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

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

  1. 如何初始化指向最初有 N 项的对象的指针列表?我应该使用 operator new 来分配内存吗?
  2. 如果我想从列表和程序内存中完全删除(释放)一个项目 space,我应该使用 pop 还是 remove 或 erase?差异?
  3. 我应该在迭代列表时使用运算符 delete 还是 .erase .remove 足以释放 space?

.

   class myclass { /* whatever attributes, methodes */  };

    list<myclass *> lst (5); //5 pointers will be NULL this way

for (list<myclass *>::iterator it=lst.begin(); it != lst.end(); it++)  {
   myclass *obj= *it;
   delete obj;              //error
   it = lst.erase(it);
}

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

最初不要尝试使用指针列表。当你这样做时,使用 smart 指针列表,但这已经是一个高级主题。应完全避免 "dumb" 指针列表。

虽然我认为您应该听听其他人的意见,但我想我仍然会回答您的问题,以便您在需要了解时知道答案。智能指针绝对是现在最好用的,但是当我在 C++ 中学习指针时,我最初使用 new/delete 我觉得它比直接使用智能指针更能帮助你理解(我知道你说你不知道它们是什么,所以它们只是为您管理内存)。

how to initialize a list of pointers to objects initially with N items ? should i use the operator new to allocate memory?

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

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

if i want to delete completely (free) an item from a list and program memory space, should i use pop or remove or erase ? differences?

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

should i use operator delete while iterating a list or .erase .remove is enough to free space ?

.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++ 的最佳方法,但它应该按要求回答您的问题。

  1. how to initialize a list of pointers to objects initially with N items ? should i use the operator new to allocate memory?

不要。让列表处理分配和释放。

lst.push_back(myclass());

如果您有许多项目要进入列表,您可以利用初始值设定项。下面使用一个myclass构造函数,以一个string和一个int为例

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

如果这是一个需要使用指针的赋值,绝对使用 new 而不是 malloc 并且它是分配存储空间的家族,但考虑这是最后的手段。

首选是使用智能指针。其中最大的两个是 unique_ptr and shared_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。

但我认为这与直接包含我的class 的列表没有任何优势,除非我的class 是class 层次结构的基础class。如果您处于学习 C++ 的早期阶段,请在走这条路之前阅读和练习一些基础知识。

list<shared_ptr<myclass>> lst;

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

使我的 class 成为可与他人共享的引用计数。当每个用户都处理完他们的 shared_ptr 后,myclass 将被销毁。这对于具有回调的系统非常有用。当回调触发时,回调对象将在那里,防止各种有趣的段错误。缺点是对象的生命周期是模糊的。何时销毁取决于未完成的shared_ptrs.

不允许循环引用 shared_ptr,因为引用计数永远不会降为零。可能内置了一些非常偷偷摸摸的代码来提供帮助,但我不会指望它。反正程序设计不好。

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

lst.push_back(new myclass());
  1. if i want to delete completely (free) an item from a list and program memory space, should i use pop or remove or erase ? differences?

remove 列表不存在。 pop,看你用哪个,要么去掉first or last element. Use pop if the list represents a queue or a stack. erase 可以去掉任何元素,只要你知道它在哪里。找到它可能需要搜索。

对于存储的对象,list<myclass> 您可能无法取回任何内存。该列表可能会保存分配的 RAM,因此以后不必再次请求它。坦率地说,我不确定列表的标准政策是什么。对于vectors, the object is destroyed, but the space remains allocated unless you manually force a resizing. I believe list behaves the same way because of the presence of the resize方法和文档的写法。

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

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

  1. should i use operator delete while iterating a list or .erase .remove is enough to free space ?

我在上面对 2 的回答中提到了。使用指针,从列表中删除只会删除指向 myclass 的指针,而不会留下指向 myclass 的指针,并且 RAM 会丢失.使用智能指针,myclass 被智能指针销毁,无需进一步努力。

但是如果 RAM 被列表保留以供重用,您可能不会收回任何明显数量的 RAM。