#c #foreach #stl-algorithm #function-object
#c #foreach #stl-алгоритм #функция-объект
Вопрос:
#include <list>
#include <algorithm>
class Abstract
{
//contains a pure virtual function
};
class Mock
{
public:
Mock();
~Mock()
{
std::for_each(m_abs_list.begin(), m_abs_list.end(), my_func);
}
void my_func(Abstract *ele){delete ele;}
private:
std::list <Abstract *> m_abs_list;
};
По сути, я пытаюсь вызвать деструктор для каждого Abstract
объекта в m_abs_list
. Это может быть легко достигнуто с помощью for
цикла. Но я пытаюсь использовать for_each
в этом контексте.
При компиляции я получаю ошибку:
/usr/include/c /4.2/bits/stl_algo.h: In function '_Function std::for_each(_InputIterator, _InputIterator, _Function) [with _InputIterator = std::_List_iterator<Abstract *>, _Function = void (Mock::*)(Abstract *)]'
/usr/include/c /4.2/bits/stl_algo.h:159: error: must use '.*' or '->*' to call pointer-to-member function in '__f (...)'.
Как мне обойти ошибку компиляции?
Ответ №1:
Не обходите это, исправьте! 😉 Вы написали .
вместо ,
здесь:
for_each(m_abs_list.begin(). m_abs_list.end(), my_func)
Кроме того, нет точки с запятой ( ;
).
Комментарии:
1. Это ошибка в коде, который он опубликовал, да, но не причина его проблемы.
2. @MooingDuck: Я думал, что я единственный, кто заметил!
3.
my_func
это нестатическая функция-член, поэтомуfor_each
она все равно не будет работать!4. также отсутствует std:: перед for_each .
5. @DeadMG, мычащая утка: Ты прав, и я должен научиться читать. Однако я заметил еще одну вещь:
Class
верхний регистрC
. Если бы автор вопроса опубликовал фактический код, возможно, я бы не стал тратить время каждого на исправления орфографии.
Ответ №2:
Несколько глупых опечаток, но что более важно, вы пытаетесь передать функцию-член, как если бы это была свободная функция. Функции-члены требуют специального использования — в общем случае вы можете использовать boost:bind . Но в этом случае, поскольку он не зависит ни от каких переменных экземпляра, проще всего сделать его статическим.
Да, и, кстати, используйте интеллектуальные указатели. Серьезно. Не используйте необработанные указатели.
Комментарии:
1. Похоже, нет никаких причин для того, чтобы функция даже была членом.
Ответ №3:
Вы не можете использовать my_func подобным образом, потому что это функция-член, а каждая функция-член связана с классом и для ее использования требуется указатель на этот класс. В стандартном C вам пришлось бы использовать функции привязки (например, bind1st ) для создания функтора, который содержит указатель на ваш объект, который вы можете передать функции-члену.
Конечно, вы также можете напрямую создавать функтор или использовать свободную функцию (или статическую функцию в классе). Если вы используете boost, вы также можете использовать функции boost::bind, которые проще (это не единственное их преимущество) писать, чем стандартные. (и я не упоминаю лямбды boost или C 11).
Если вы не знаете, что такое функтор, это класс, который переопределяет его функцию operator() . Все алгоритмы STL созданы для их использования.
В вашем случае простой способ — просто создать свободную функцию. Конечно, вам также следует использовать, если вы можете использовать интеллектуальные указатели, такие как boost::shared_ptr, вы получите значительные преимущества в управлении памятью.
Ответ №4:
Как указывали другие, это не «правильный» способ сделать это. Но вот что вы пытаетесь сделать…
std::for_each(m_abs_list.begin(), m_abs_list.end(),
std::bind1st(std::mem_fun<void, Mock, Abstract*>(amp;Mock::my_func), this);
Я нахожусь вдали от своей системы разработки, поэтому могут быть некоторые синтаксические ошибки.
Ответ №5:
Для управления памятью следует использовать интеллектуальный указатель (отличный от auto_ptr).
Таким образом, когда ваш список участников будет уничтожен, он освободит всю выделенную кучу памяти вместе с ним.
Однако, если вы не хотите этого делать и если вы не ограничены использованием компилятора, который не поддерживает лямбды…
#include <list>
#include <algorithm>
class Abstract
{
//contains a pure virtual function
};
class Mock
{
public:
Mock();
~Mock()
{
std::for_each(m_abs_list.begin(), m_abs_list.end(), [](Abstract *ele)
{ delete ele; });
}
private:
std::list <Abstract *> m_abs_list;
};
Комментарии:
1. Вау, это совершенно ужасно. Вы исправляете крошечную ошибку и игнорируете огромную, вредную дыру в управлении памятью.
2. Вы, должно быть, пропустили мое самое первое предложение.