2013-06-26 5 views
2

Следующий код выдает ошибку сегментации, и я не знаю, почему:C++ Lambda ошибка сегментации

myTree<int> tree; 
    tree.insert(10); // not important 

    std::vector<int> v = tree.toVector(); // Segmentation fault 

Это код myTree (уменьшенный, не компилируется, просто достаточно, чтобы понять, о чем это):

template<class T> struct node { 
    T key; 
    node *left; 
    node *right; 
    int count; 

    node(const T &k=T(), node *l=0, node *r=0) { 
     key = k; 
     left = l; 
     right = r; 
     count = 1; 
    } 
}; 

template<class T> class myTree { 
public: 
    myTree() { 
     root = 0; 
    } 

    void traverseInOrder(void (*visitFunc)(node<T>* n)) { 
     traverseInOrder(visitFunc, root); 
    } 

    std::vector<T> toVector() { 
     std::vector<T> v; 
     traverseInOrder([&](node<T>* n) { 
      v.insert(v.end(), n->count, n->key); 
     }); 
     return v; 
    } 
private: 
    void traverseInOrder(void (*visitFunc)(node<T> *n), node<T> *n) { 
     if (n == 0) { 
      return; 
     } else { 
      if (n->left != 0) { 
       traverseInOrder(visitFunc, n->left); 
      } 

      (*visitFunc)(n); 

      traverseInOrder(visitFunc, n->right); 
     } 
    } 

    node<T> *root; 
}; 

неисправность сегментации происходит в этой строке:

v.insert(v.end(), n->count, n->key); 

говорит окно переменных NetBeans v - OUT_OF_SCOPE.

Вопрос: Я правильно использую лямбду?

Примечание: Я использую g ++ (GCC) 4.7.2 (Cygwin).

+3

Вопрос в том, как понимать код, который вы написали, и как использовать отладчик? –

+0

Какова ценность t? Кроме того, попробуйте выполнить шаг в вызове insert() и узнайте, что такое значение 'this'in там. Сравните с '& v' в фрейме стека выше, где определяется' v'. – Arkadiy

+4

Ах - это интересно. В соответствии с этим (http://stackoverflow.com/a/2993349/3458) в качестве указателей функций могут передаваться только безгарантные lambdas. У вас нет апатридов. – Arkadiy

ответ

5

Как уже отмечалось в комментариях @Arkadiy, лямбда состояния не распадается на указатель функции. Исправление написать свой traverseInOrder в качестве шаблона, который принимает вызываемый объект

template<class Func> 
void traverseInOrder(Func visitFunc)) { 
    traverseInOrder(visitFunc, root); 
} 

В качестве альтернативы, вы могли бы быть более типобезопасными и дать ему подпись, которая принимает std::function, которая возвращает void и принимает node<T>*

void traverseInOrder(std::function<void(node<T>*)> visitFunc)) { 
    traverseInOrder(visitFunc, root); 
} 
+1

или используйте std :: function – Arkadiy

+0

Спасибо! Извините за отсутствие компилятивного примера. – robert

+0

@Arkadiy tnx, обновлено. – TemplateRex