использование for_each в C

#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. Вы, должно быть, пропустили мое самое первое предложение.