【问题标题】:Deletion of elements from std::vector从 std::vector 中删除元素
【发布时间】:2021-03-13 11:24:15
【问题描述】:

我想从 std::vector 中删除所有元素

    for (Entity * cb : cbs)
    {
        delete cb;
    }

有没有更好的方法来做到这一点?

【问题讨论】:

  • 这能回答你的问题吗? Delete all items from a c++ std::vector
  • 这个方法没问题,但我建议之后调用cbs.clear()清空向量。
  • 只是为了清楚起见,因为您没有指定:您是在询问应该删除的对象的原始指针向量,对吧?不只是清空向量本身?
  • @Useless 是的,它只是指针向量。我想说的不仅仅是删除。它可以是对元素的任何操作,但对所有元素都一样。

标签: c++ c++11 stdvector


【解决方案1】:

std::for_each 可以替代显式循环:

std::for_each(cbs.begin(), cbs.end(), [](Entity *cb){
    delete cb;
});

【讨论】:

  • 我只需要问一下,当显然有许多诸如此类的问题的欺骗目标时,为什么您会鼓励 OP 通过回答这些问题来提出这些问题?花了 5 秒时间找到了一个欺骗目标。
  • 我认为清除向量不会删除指针。
  • 这与在每个元素上调用 delete 的目的不同。我认为您可能暗示操作应该放弃指针或在其向量中使用智能指针。但我怀疑操作人员会知道这一点,因为他们在问这个问题。
  • @dfrib Op 是一个相对较新的用户,网站鼓励我们保持友好。站点不会因重复关闭问题而授予任何声誉。如果这是他们想要的行为,他们应该为此奖励声誉。
  • 我有点不确定,但可以有一个单线 lamda 函数来解决这个问题。我的意思是对所有元素执行相同的操作,必须有更好的方法而不是循环。
【解决方案2】:

您在 cmets 中阐明您有一个原始指针向量,并希望删除它们指向的所有对象。

那么你是怎么做到的呢?

你没有!

在 C++ 中,我们不进行手动内存管理(原始 new/delete)。它有问题(任何异常都会使您泄漏内存),容易出错且令人困惑(谁应该删除对象)。相反,我们使用 RAII。为此,我们有智能指针。所以请使用std::unique_ptrstd::shared_ptr,一切都会为您正确管理。

可以是对元素的任何操作,但对所有元素都一样。

像你这样的循环范围是惯用的方法:

for (auto&& elem : vector)
{
    foo(elem);
}

【讨论】:

    【解决方案3】:

    使用共享或唯一指针。这会导致在清除向量时自动删除(或者在您不清除的情况下导致向量的析构函数)。

    #include <iostream>
    #include <memory>
    #include <vector>
    
    class Test
    {
    private:
        size_t m_index;
    public:
        Test(size_t index)
            : m_index(index)
        {
        }
    
        void PrintIndex()
        {
            std::cout << m_index << std::endl;
        }
    
        ~Test()
        {
            std::cout << "destructor invoked for " << m_index << std::endl;
        }
    };
    
    int main()
    {
        std::vector<std::unique_ptr<Test>> v;
    
        for (size_t i = 0; i < 5; ++i)
        {
            v.emplace_back(new Test(i));
        }
    
        for (auto& t : v)
        {
            t->PrintIndex();
        }
    
        //v.clear();
    
        return 0;
    }
    

    至于评论中提到的对每个元素执行其他任意操作:

    还有其他方法可以实现此结果,但没有什么比范围 for 循环更棒的了;恕我直言;毕竟它只是 3 行简单的行(加上循环体)。

    【讨论】: