Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > неявное преобразование итератора в указатель


Автор: neosapient 22.12.2009, 12:09
Здравствуйте.

В VC6 использовал следующий прием для копирования элементов в контейнере: переопределял операцию присваивания значения по указателю.
Далее в коде пробую присвоить значение элементу через итератор указывающий на другой элемент в vectore.
VC6 спокойно воспринимает преобразование из итератора в указатель. VC9 ругается на подобное преобразование. 
Цитата

c:\documents and settings\user\desktop\ublas\testiterator\main.cpp(50) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Ty,_Alloc>' (or there is no acceptable conversion)
with
[
    _Ty=MyStruct,
    _Alloc=std::allocator<MyStruct>
]
c:\documents and settings\zhukov\desktop\ublas\testiterator\main.cpp(13): could be 'MyStruct &MyStruct::operator =(const MyStruct &)'
c:\documents and settings\zhukov\desktop\ublas\testiterator\main.cpp(18): or       'MyStruct &MyStruct::operator =(const MyStruct *)'
while trying to match the argument list '(MyStruct, std::_Vector_iterator<_Ty,_Alloc>)'
with
[
     _Ty=MyStruct,
    _Alloc=std::allocator<MyStruct>
]


Подскажите, как правильно переписать пример для VC9 ?

Вот код примера
Код

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#include <vector>
#include <list>
using namespace std;


class MyStruct
{
public:
    MyStruct &operator=(const MyStruct &other)
    {
        memcpy(this, &other, sizeof(MyStruct));
        return *this;
    }
    MyStruct &operator=(const MyStruct *other)
    {
        if(other==NULL){
            memset(this, 0, sizeof(MyStruct));
            return *this;
        }
        else{
            memcpy(this, other, sizeof(MyStruct));
            return *this;
        }
    }
public:
    int alfa;
    double betta;
};

int main(int argc,char * argv[])
{
    int i;
    MyStruct  mass[3] = {{1,1.0},{2,2.0},{3,3.0}};
    vector<MyStruct> Vect;
    list<MyStruct> List;
    vector<MyStruct>::iterator Iter;
    MyStruct item;
    // заполняем вектор
    Vect.clear();
    for(i=0; i<3; i++){
        Vect.push_back(mass[i]);
    }
    // заполняем список
    List.clear();
    for(Iter = Vect.begin(); Iter != Vect.end(); ++Iter){
        item = Iter;  // <-- в этом месте в VC9 итератор перестает восприниматься как указатель
        List.push_back(item);
    }
    //----
    return 0;
}

Автор: bsa 22.12.2009, 12:16
neosapient, MyStruct &operator=(const MyStruct *other) - вообще выкини.
Код
item = Iter;  // <-- в этом месте в VC9 итератор перестает восприниматься как указатель
замени на
Код
item = *Iter;

Автор: neosapient 22.12.2009, 13:12
Ещё один вопрос, по обратной задаче
Преобразую итератор к NULL-евому указателю. Но компилятор ругается. Как это можно исправить.
Цитата

1>c:\documents and settings\user\desktop\testiterator\main.cpp(43) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\vector(405): could be 'std::_Vector_iterator<_Ty,_Alloc> &std::_Vector_iterator<_Ty,_Alloc>::operator =(const std::_Vector_iterator<_Ty,_Alloc> &)'
1>        with
1>        [
1>            _Ty=MyStruct,
1>            _Alloc=std::allocator<MyStruct>
1>        ]
1>        while trying to match the argument list '(std::_Vector_iterator<_Ty,_Alloc>, int)'
1>        with
1>        [
1>            _Ty=MyStruct,
1>            _Alloc=std::allocator<MyStruct>
1>        ]


Код

int main(int argc,char * argv[])
{...
    Iter=NULL;
}

Автор: bsa 22.12.2009, 21:34
neosapient, ты видимо вообще не понимаешь, что такое итератор. Итератор - это объект, который ведет себя как указатель. В частности, есть итераторы ввода (std::istream_iterator) и вывода (std::ostream_iterator)... Как ты их преобразуешь в указатели?

Итератор, обычно, это способ доступа к данным контейнера. Соответственно, контейнер всегда имеет методы, которые позволяют узнать начальный итератор и конечный (который ни на что не ссылается - аналог NULL). Эти методы у стандартных контейнеров называются begin() и end() (или rbegin() и rend(), если нужна обратная последовательность перебора). Таким образом, когда итератор после ряда операций приращения стал равен end(), то достигнут конец данных.

В твоем случае есть смысл заменить на Iter = Vect.end(), только имей в виду, что Vect.end() != NULL и операция if (Iter) {}, если скомпилируется, то будет всегда true.

Автор: Earnest 23.12.2009, 07:29
neosapient, в старой среде VC^6 действительно использовалась версия STL, где итераторы, по крайней мере, вектора и были реализованы как указатели. Но уже с 7й версии это не так. Итератор - не указатель! Но преобразовать итератор к указателю на элемент легко:
 CItem* pItem = &(*iter), где iter - это итератор контейнера, в котором лежат CItem. Т.е. сначала разыменовываем и получаем ссылку на элемент, а потом берем адрес.
Вот наоборот сделать нельзя (в общем случае) - т.е. из указателя в итератор. Т.е. для вектора-то можно всегда, пользуясь тем, что память обязательно непрерывна, а вот для других контейнеров - очень сильно зависит от реализации STL, и не все это позволяют. 
Грубо говоря, нужно смотреть, есть ли у итератора открытый конструктор от ссылки или указателя на значение.
Так что не стоит так делать.

Автор: maxim1000 23.12.2009, 18:51
Цитата(Earnest @  23.12.2009,  07:29 Найти цитируемый пост)
Но преобразовать итератор к указателю на элемент легко:
 CItem* pItem = &(*iter), где iter - это итератор контейнера, в котором лежат CItem. Т.е. сначала разыменовываем и получаем ссылку на элемент, а потом берем адрес.

маленькая добавочка:
TContainer::end() вернёт вполне корректный объект-итератор, который не стоит разыменовывать, да и указатель ему никакой не соответствует

конечно, для разыменовываемых итераторов такой способ работает

Автор: Adjusly 24.1.2023, 01:11
Модератор: Сообщение скрыто.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)