Функция очистки шаблона вектора указателей не может скомпилироваться с сообщением «неопределенная ссылка»

StackOverflow https://stackoverflow.com/questions/914460

  •  06-09-2019
  •  | 
  •  

Вопрос

Для своей программы я создал небольшую функцию для очистки различных имеющихся у меня указателей std::vectors.

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, поэтому не могу предположить, в чем здесь может быть проблема.Любая помощь действительно ценится.Заранее спасибо!

-Лефтерис

Это было полезно?

Решение

Горячее исправление

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

  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 ценности).Одним из возможных решений было бы использование Контейнер указателя повышения

Другие советы

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

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

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

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.Код будет сгенерирован при первом вызове функции, а это означает, что компилятору необходимо знать определение функции.Переместите функцию в заголовочный файл, чтобы компилятор мог ее найти.

Наконец, рассмотрите возможность использования вещей, более подходящих для этого:

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

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

Не является ли редизайн дубликатомОчистка-списка-векторов-указателей-stl

Примечание

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top