【问题标题】:Clarification on lists and removing elements澄清列表和删除元素
【发布时间】:2009-10-14 11:33:09
【问题描述】:

如果我有一个list<object*>>* queue 并且想弹出列表中的第一个对象并将其交给程序的另一部分,使用是否正确(粗略代码):

object* objPtr = queue->first();
queue->pop_first();
return objPtr;  // is this a pointer to a valid memory address now?

?

根据http://www.cplusplus.com/reference/stl/list/pop_front/ 上的文档,它调用了已删除元素的析构函数,但我很困惑它是指链表的节点对象,还是实际存储的“用户”对象。

编辑:我可能是front 而不是first,我的错。

【问题讨论】:

    标签: c++ list stl pointers object


    【解决方案1】:

    是的,它是一个有效的指针。 List 不会释放你分配的内存。 List 将销毁其内部而不是用户对象。

    【讨论】:

      【解决方案2】:

      是的,它是有效的:由于您将 pointers 放入列表中,因此只有 pointer 被销毁,而不是对象本身。

      【讨论】:

        【解决方案3】:

        是的objPtr 包含指向有效内存的指针。

        当您将元素插入std::list 时,list 会复制它。在您的情况下,元素是一个地址(指针),因此 list 会复制地址并将其存储。

        object * optr = queue->pop_front();
        

        optr 现在指向对象

        queue->pop_front();
        

        list 中删除元素(地址/指针),optr 已经指向您的对象。

        在你完成对象后不要忘记删除它,否则你会导致内存泄漏。

        例子:

        #include <iostream>
        #include <list>
        
        using namespace std;
        
        struct A
        {
            static int count;
        
            A() : val(count++) { cout << "A(" << val << ")" << endl; }
            ~A()               { cout << "~A(" << val << ")" << endl; }
        
            int val;
        };
        
        int A::count = 0;
        
        ostream& operator<<(ostream& os, A& a) { return os << a.val; }
        
        int main()
        {
            list<A*> alist;
        
            for (unsigned int i = 3; i; --i) alist.push_back(new A());
            for (unsigned int i = 3; i; --i)
            {
                A * aptr = alist.front();
                alist.pop_front();
                cout << *aptr << endl;
                delete aptr;
                aptr = 0;
            }
        }
        

        【讨论】:

          【解决方案4】:

          标准确实说 (23.2.2.3/5) 调用了元素类型的析构函数。但是这个类型在这里是指针,而指针的析构函数什么都不做……

          【讨论】:

            【解决方案5】:

            您的代码很好,但最好使用list&lt; boost::shared_ptr&lt;object&gt; &gt;

            
               shared_ptr < object> objPtr = queue->first();
               queue->pop_first();
               return objPtr;  
            

            【讨论】:

            • 我没有投反对票,但这是我的观点:你不能简单地从本机指针切换到 shared_ptr 所以这个答案不是很有用。
            • 在不完全了解需求的情况下,为什么使用 shared_ptr 更好。
            • 因为如果有人不知道列表是否在删除包含的指针时也会删除指向的对象,那么某人非常不太可能获得手动内存管理错误?
            • @mxp: 1) 这在给出的代码中肯定是微不足道的。 2) 切换到智能指针的 IME 体验大多不平凡,因为代码使用裸指针做可疑的事情。 3) 在容器中使用裸指针势必造成泄漏。
            • 我投了反对票。上面给出的原因是我投反对票的原因。 boost::shared_ptr 既不是问题的答案,也不是客观上比原始指针“更好”。有些应用程序不需要 shared_ptrs。如果它们总是“更好”,那么默认情况下 C++ 将被垃圾收集。这不是因为它们并不总是“更好”。仅仅因为将裸指针放入容器中更加困难,并不能使 shared_ptrs 自动化。仍然,这个问题没有得到回答。
            【解决方案6】:

            当您移除元素时,STL 容器不会破坏分配在堆上的用户对象。

            class A
            {
            
            };
            
            
            list<A*> PointerToObjectList;
            
            A* ptr = new A();
            PointerToObjectList.push_back(ptr);
            

            如果您从列表中删除 ptr,则列表不会自动删除该对象。一旦不再使用对象,您需要显式调用 delete。

            【讨论】:

              猜你喜欢
              • 2019-12-18
              • 2015-08-03
              • 2023-03-03
              • 2019-04-06
              • 2015-12-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多