【问题标题】:C++ template function that receives std::vector as argument接收 std::vector 作为参数的 C++ 模板函数
【发布时间】:2011-08-30 19:46:59
【问题描述】:

我需要创建一个模板函数,它接收某种类型的 std::container 作为参数 - 比如说 std::vector 并从该容器中删除所有元素。我需要一个与此等效的函数:

for_each(some_vector.begin(), some_vector.end(), [](some_vector_type* element){delete element;}); 

调用应该是这样的:

delete_all_elements(some_vector);

这可能吗?

编辑:我想在 delete_all_elements 中使用第一个代码

【问题讨论】:

  • 你在使用 C++11 并且还在写 delete ?你确定你不能用std::vector<std::unique_ptr<T>> 让你的问题消失吗?
  • 作为奖励的答案:如果你删除了一些指针,最后:要么将那些删除的指针放到NULL(或 C++11 的 nullptr),要么从容器中删除这些指针(除非您确定容器本身很快就会被销毁)。悬空指针不是一个好的设计选择... :-) ... 阅读所有答案后,我很惊讶没有人会做最后的清理工作。
  • 使用std::unique_ptr 消除问题的另一个原因是,当您想要一个指向数组第一个元素的指针向量而不是单个对象时,您可以切换到@987654328 的向量@。你必须编写一个与delete_all_elements 相同的delete_all_array_elements 函数,除了使用delete[] 而不是delete,然后在没有类型系统帮助的情况下调用正确的函数。

标签: c++ c++11


【解决方案1】:

为什么不呢?

template <typename C>
void delete_all_elements(C& container) {
    std::for_each(
        container.begin(), container.end(),
        [](typename C::value_type ptr) { delete ptr; }
    );
    container.clear();
}

您可以添加例如static_assert(std::is_pointer&lt;typename C::value_type&gt;::value, "Elements must be pointers"); 开头,以确保您不会尝试删除非指针。

【讨论】:

  • 谢谢!我不知道 C::value_type。
  • 在这种情况下,我认为这会有所不同。但在这种情况下,可能值得使用C::reference 作为您的默认值,以防止在更改代码时意外复制。
  • 如果要传递容器引用,请在末尾添加 container.clear(),这样它们就不会留下一个悬挂指针的容器。
【解决方案2】:

为什么不做几乎所有 STL 算法的事情:

template<typename Iterator>
void delete_all_elements(Iterator begin, Iterator end) {
    while (begin != end) {
        delete *begin;
        ++begin;
    }
}

【讨论】:

    【解决方案3】:

    规范的方式是:

    template <typename I>
    void delete_all_elements(I begin, I end)
    {
        for (; begin != end; ++begin) delete *begin;
    }
    

    【讨论】:

      【解决方案4】:

      您是否在寻找这个(C++03 解决方案):

      template<typename Container>
      void delete_all(const Container & c)
      {
         typename Container::const_iterator begin = c.begin(), end = c.end();
         while ( begin != end ) { delete *begin; ++begin; }
      }
      

      【讨论】:

      • 我可能是错的,但是为您的“全部删除”功能接受 const 容器是不好的风格:虽然合法,但您仍在语义上修改容器内的值(破坏容器内的对象) .
      • Hope, its okay now. And const-ness is no problem here. const int *p = new int; delete p; perfectly value! :是的,我知道。这就是我在评论中写“虽然合法”的原因。但从语义上讲这是错误的,因为无论间接(这里是“双指针”)如何,容器的每个项目都包含一个指向有效对象的值。在函数结束时,这些值不再指向有效对象(它们已被销毁)。因此,在某种程度上,您修改了容器,这是您承诺不会在函数原型中将其声明为 const 的做法。
      • Nawaz:并不是说它是非法的,而是它的形式很糟糕,因为该函数暗示它不会改变数据的公共内容,但会继续爆破所有的指针。
      • @Nawaz : If you make this non-const, then you cannot call this function on const vector. 当然!这正是重点:重点是没有给你的功能尽可能多的权力。关键是让用户查看界面(这里是函数原型)时尽可能清晰:const 是在这里告诉用户“我保证不会碰你容器的内容”。然后,在正文中,您破坏了向量的内容。这意味着你对用户撒谎,这在语义上是错误的。
      • @paercebal:C++03 标准要求 end 是所有容器中的常数时间操作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多