2012-05-06 8 views
0

У меня есть класс TreeVertex:Список Итератор не перебирает все элементы

// TreeVertex.h 
#ifndef __TREEVERTEX__ 
#define __TREEVERTEX__ 

#include <list> 

using namespace std; 

class TreeVertex { 
public: 
    TreeVertex(list<int>, TreeVertex* = NULL); 
    list<int> getItemset(); 
private: 
    list<int> Itemset; 

    TreeVertex * Parent; 
    TreeVertex * LeftChild; 
    TreeVertex * RightSibling; 
}; 

#endif // __TREEVERTEX__ 

// TreeVertex.cpp 

#include "TreeVertex.h" 

TreeVertex::TreeVertex(list<int> Itemset, TreeVertex* Parent) : Itemset(Itemset),  Parent(Parent), LeftChild(NULL), 
    RightSibling(NULL) { } 

list<int> 
TreeVertex::getItemset() { 
    return Itemset; 
} 

и основная функция, как это:

#include <iostream> 
#include "TreeVertex.h" 

using namespace std; 

int main (int argc, const char ** const argv) 
{  
    list<int> tmpList1; 
    tmpList1.push_back(1); 

    TreeVertex * tmpTreeVert1 = new TreeVertex(tmpList1); 

    list<int> tmpList2; 
    tmpList2.push_back(2); 

    TreeVertex * tmpTreeVert2 = new TreeVertex(tmpList2); 

    list<int> newVertItemset; 

    newVertItemset.push_back(tmpTreeVert1->getItemset().front()); 
    newVertItemset.push_back(tmpTreeVert2->getItemset().front()); 

    cout << newVertItemset.front() << " " << newVertItemset.back() << endl; 

    TreeVertex * newTreeVert = new TreeVertex(newVertItemset); 

    cout << newTreeVert->getItemset().front() << " " << newTreeVert->getItemset().back() << endl; 

    for (list<int>::iterator it = newTreeVert->getItemset().begin(); it != newTreeVert->getItemset().end(); ++it) { 
     cout << (*it) << " "; 
    } 

    cout << endl; 

    cout << newTreeVert->getItemset().size() << endl; 
    return 0; 
} 

Выход выглядит следующим образом:

Следующая до последнего выхода (первый сингл "2"), должно быть "1 2", как и другие.

Любые идеи, почему итератор не пересекает первый элемент?

Спасибо.

+1

Не используйте '__TREEVERTEX__' в качестве защитника включения, имена, начинающиеся с двойного подчеркивания, зарезервированы для реализации. Лучшим защитником заголовка будет просто 'TREEVERTEX_H'. Почему вы создаете объекты «TreeVertex» в куче? Если вы создадите их в куче, вы должны помнить об их удалении! –

+0

Спасибо. Я это сделаю. В этом примере вы правы: мне не нужно создавать объекты в куче. В реальном коде мне нужны указатели. –

ответ

8

Проблема с этим:

list<int> 
TreeVertex::getItemset() { 
    return Itemset; 
} 

Everytime вы вызываете эту функцию, она возвращает копию объекта, что означает, что следующий цикл не должен работать:

for (list<int>::iterator it = newTreeVert->getItemset().begin(); 
         it != newTreeVert->getItemset().end(); ++it) { 

как это сравнивает итераторы от двух разных объектов. Решение состоит в том, чтобы вернуть ссылку как:

list<int> & //<--- return reference, not copy 
TreeVertex::getItemset() { 
    return Itemset; 
} 

Но лучшим решением будет удалить getItemset вообще и вместо этого, добавьте begin() и end() члены функции:

//define these typedefs first in the public section 
typedef list<int>::iterator iterator; 
typedef list<int>::const_iterator const_iterator; 

iterator begin() { return itemSet.begin(); } 
iterator end() { return itemSet.end(); } 

, а затем написать for петля как:

for(TreeVertex::iterator it = newTreeVert->begin(); 
         it != newTreeVert->end(); ++it) { 

Если вы можете использовать C++ 11, то вы должны добавить их:

//note : the function names start with `c` 
const_iterator cbegin() const { return itemSet.cbegin(); } 
const_iterator cend() const { return itemSet.cend(); } 

Или, если вы используете C++ 03 (и не может использовать C++ 11), а затем добавить их:

const_iterator begin() const { return itemSet.begin(); } 
const_iterator end() const { return itemSet.end(); } 
+1

Отлично. Благодарю. –