2013-04-19 3 views
1

Я хочу построить вложенные петли над массивами объектов, имея довольно сложную структуру данных. Поскольку я использую массивы, я хочу использовать их итераторы. После того, как я получил неожиданные результаты, которые я сводились проблему в следующем фрагменте кода, который показывает мои итераторы быть равны, когда я ожидаю, что они разные:Вложенный цикл итератора, почему итераторы равны? - C++

vector<int> intVecA; 
vector<int> intVecB; 

intVecA.push_back(1); 
intVecA.push_back(2); 

intVecB.push_back(5); 
intVecB.push_back(4); 

Foo fooOne(intVecA); 
Foo fooTwo(intVecB); 

vector<int>::const_iterator itA = fooOne.getMyIntVec().begin(); 
vector<int>::const_iterator itB = fooTwo.getMyIntVec().begin(); 
cout << "The beginnings of the vectors are different: " 
    << (fooOne.getMyIntVec().begin() == fooTwo.getMyIntVec().begin()) << endl; 
cout << (*(fooOne.getMyIntVec().begin()) == *(fooTwo.getMyIntVec().begin())) << endl; 
cout << (&(*(fooOne.getMyIntVec().begin())) == &(*(fooTwo.getMyIntVec().begin()))) << endl; 
cout << "But the iterators are equal: " 
    << (itA==itB) << endl; 

Это дает:

The beginnings of the vectors are different: 0 
0 
0 
But the iterators are equal: 1 

Такое поведение не имеет смысла для меня, и я был бы рад услышать объяснение.

Foo представляет собой простой объект, содержащий вектор и функцию геттер для него:

class Foo { 
    public: 
    Foo(std::vector<int> myIntVec); 

    std::vector<int> getMyIntVec() const { 
    return _myIntVec; 
    } 

    private: 
    std::vector<int> _myIntVec; 
}; 

Foo::Foo(std::vector<int> myIntVec) { 
    _myIntVec = myIntVec; 
} 

При первом копировании векторов проблема исчезает. Зачем?

vector<int> intVecReceiveA = fooOne.getMyIntVec(); 
vector<int> intVecReceiveB = fooTwo.getMyIntVec(); 

vector<int>::const_iterator newItA = intVecReceiveA.begin(); 
vector<int>::const_iterator newItB = intVecReceiveB.begin(); 

cout << "The beginnings of the vectors are different: " 
    << (intVecReceiveA.begin() == intVecReceiveB.begin()) << endl; 
cout << "And now also the iterators are different: " 
    << (newItA==newItB) << endl; 

производит:

The beginnings of the vectors are different: 0 
And now also the iterators are different: 0 

Дополнительные примечания: мне нужны эти вложенные циклы в функциях, которые должны быть чрезвычайно эффективными в отношении времени вычислений, поэтому я не хотел бы делать ненужных операций. Поскольку я новичок в C++, я не знаю, действительно ли копирование векторов займет дополнительное время или же они будут копироваться внутри страны в любом случае. Я также благодарен за любые другие советы.

+0

«Я не знаю, действительно ли копирование векторов займет дополнительное время» - да, это будет. –

ответ

2

Проблема заключается в том, что ваш сбруя в Foo:

std::vector<int> getMyIntVec() const { 
return _myIntVec; 
} 

Я не возвращает _myIntVec, он возвращает копию из myIntVec. Вместо этого он должен выглядеть следующим образом:

const std::vector<int>& getMyIntVec() const { 
return _myIntVec; 
} 

В противном случае при создании итераторов они создаются из копий, которые непосредственно выброшены поэтому компилятор C++ повторно адрес. Вот почему вы получаете «равные» итераторы, по крайней мере, я так думаю.

+0

Это действительно решило проблему. Благодарим вас за быстрый, точный и пояснительный ответ. Это имеет смысл для меня сейчас, хотя мне непонятно, почему копии сразу отброшены. – user2296653

0

Вы понимаете, что сравниваете вещи не так? Если сравнить a == b, даже если вы пишете

cout << "a is different from b: " << (a==b) << endl; 

Выходной сигнал покажет, если оба элемента одинаковы не отличаются. Чтобы проверить, отличаются ли две вещи, используйте != вместо ==.

+0

Извините за мою явно нечеткую конструкцию строк вывода и сравнений. Моя идея состояла в том, чтобы определить равенство с истиной и разницу с ложью, вместо того, чтобы строить утверждения как истинные. Я знал, что я сравнивал и как. – user2296653

0

Причина в том, что это неопределенное поведение для сравнения двух итераторов, которые относятся к элементам в разных контейнерах. Таким образом, нет гарантии, что вы получите. Это происходит из-за того, что getMyIntVec возвращает копию _MyIntVec и присваивает эти копии новым экземплярам vector<int>, поэтому они действительно являются итераторами двух разных копий члена _MyIntVec.

В соответствии со стандартом:

§ 24.2.1

Итератор J называется достижим из итератора я тогда и только тогда, когда существует конечная последовательность применений выражение ++ я, что делает I == J. Если j достижимо от i, они относятся к элементам той же последовательности.

и немного позже в стандарте:

§ 24.2.5

Область == для передних итераторов является то, что итераторы над одной и той же базовой последовательностью.

Это уже ответил this question

0

У вас есть серьезная логическая проблема:

cout << "The beginnings of the vectors are different: " 
<< (fooOne.getMyIntVec().begin() == fooTwo.getMyIntVec().begin()) << endl; 

Если они равны, то будет выход 1 вместо 0, которые вы обычно ожидаете.

Смежные вопросы