指针模板清除功能的向量无法使用“未定义的引用”消息进行编译

时间:2009-05-27 07:48:37

标签: c++ templates stl stdvector

对于我的程序,我做了一个小函数来清除我所拥有的各种std ::指针向量。

template <class S>
void clearPtrVector(std::vector<S*> &a,int size)
{
    for(size_t i = 0; i < size; i++)
         delete a[i];

    a.clear();
}

我必须在这里做错了,因为在析构函数中调用此函数是这样的:

clearPtrVector(neurons,neurons.size());

我两次得到以下未定义的引用:

undefined reference to `void clearPtrVector<Neuron>(std::vector<Neuron*,std::allocator<Neuron*> >&, int)'

我不得不承认我不熟悉std :: allocator是什么,所以我无法猜出这里可能出现的问题。任何帮助都非常感谢。提前谢谢!

-Lefteris

6 个答案:

答案 0 :(得分:8)

热修复

写下来:

  template <class Vector>
  void clearPtrVector(Vector &a)
  {
    for(size_t i = 0; i < a.size(); i++)
         delete a[i];

    a.clear();
  }

确保在每次使用模板之前将模板定义在编译器可以看到的位置。如果您不创建声明,则应该是安全的,否则您将收到编译错误。如果您因任何原因确实创建了声明,请仔细检查以根据需要随处包含定义。

<强>重新设计

那就是说,我认为正确的解决方案是重新考虑你的设计,并使用一个能够正确处理破坏的容器,这样你就不必手动完成,这很乏味,而且几乎不可能正确完成如果你需要异常安全。使用std::shared_ptr代替原始指针,或std::auto_ptr使用能够容纳它们的容器(std::vector无法存储auto_ptr值)。一种可能的解决方案是使用Boost Pointer Container

答案 1 :(得分:3)

您的clearPtrVector实现是否在头文件中?因为如果它位于单独的.cpp文件中,链接器将无法找到它。

答案 2 :(得分:3)

一些事情:

在原始代码中,不要传递大小;从矢量中得到它:

template <class S>
void clearPtrVector(std::vector<S*> &a)
{
    for(size_t i = 0; i < a.size(); ++i)
    {
         delete a[i];
    }

    a.clear();
}

其次,只传入向量本身,而不是它指向的类型:

template <class Vector>
void clearPtrVector(Vector &vec)
{
    for(size_t i = 0; i < vec.size(); ++i)
    {
         delete vec[i];
    }

    vec.clear();
}

第三,该错误听起来像是放在.cpp文件中。首次调用函数时将生成代码,这意味着编译器需要知道函数的定义。将函数移动到头文件中,以便编译器可以找到它。

最后,考虑使用更适合的内容:

答案 3 :(得分:2)

确保在头文件(.h,* .hpp)中具有此功能,因为如果您在头文件中使用原型在源文件中定义它,则会出现未定义的引用链接器错误。

未定义的引用错误意味着编译器已找到该函数的引用,但链接器未能在目标文件中找到该函数的引用。必须在头文件中定义任何模板函数,以便编译器能够将它放在任何使用该函数的源文件中。

答案 4 :(得分:0)

重新设计不是重复的 cleaning-up-an-stl-list-vector-of-pointers

<强>备注

如果您不使用其中一个智能指针,请使用boost::checked_delete功能而不是删除功能,以确保您没有删除不完整的类型。

答案 5 :(得分:0)

正如我在回答您的第一个问题时所提供的https://stackoverflow.com/questions/891913?sort=newest,答案如下:

template <class C> void FreeClear( C & cntr ) {
    for ( typename C::iterator it = cntr.begin(); 
              it != cntr.end(); ++it ) {
        delete * it;
    }
    cntr.clear();
}

适用于所有容器类型。请注意,size参数未提供,但是从集合中获取 - 这是设计此类函数的正确方法,将大小视为单独的值只会导致灾难。