Функция очистки шаблона вектора указателей не компилируется с сообщением «неопределенная ссылка» - PullRequest
0 голосов
/ 27 мая 2009

Для моей программы я сделал небольшую функцию, чтобы очистить различные имеющиеся у меня 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 ]

8 голосов
/ 27 мая 2009

Hot Fix

Вместо этого напишите следующее:

  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

3 голосов
/ 27 мая 2009

Несколько вещей:

В исходном коде не указывайте размер; просто получить его из вектора:

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 голосов
/ 27 мая 2009

Ваша реализация clearPtrVector находится в заголовочном файле? Потому что, если он находится в отдельном файле .cpp, компоновщик не найдет его.

2 голосов
/ 27 мая 2009

Убедитесь, что у вас есть эта функция в заголовочном файле (.h, * .hpp), потому что если вы определили ее в исходном файле с прототипом в заголовочном файле, вы получите неопределенную ошибку ссылочного компоновщика.

Неопределенная ссылка ссылка означает, что компилятор нашел ссылку на функцию, но компоновщик не смог найти ссылку на эту функцию среди объектных файлов. Любая функция шаблона должна быть определена в заголовочном файле, чтобы компилятор мог поместить ее в любой исходный файл, который использует функцию.

0 голосов
/ 27 мая 2009

Как я указал в своем ответе на ваш первый вопрос 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();
}

, который работает для всех типов контейнеров. Обратите внимание, что параметр размера НЕ предоставлен, а получен из коллекции - это правильный способ разработки таких функций, поскольку предоставление размера в качестве отдельного значения может привести только к катастрофе.

0 голосов
/ 27 мая 2009

Разве редизайн не является дубликатом чистка вверх-ан-СТЛ-лист вектор-из-указателей

Примечание

Если вы не используете один из умных указателей, используйте функцию boost :: checked_delete вместо delete, чтобы убедиться, что вы не удаляете неполный тип.

...