Разве Iterator в c ++ не является своего рода указателем? - PullRequest
5 голосов
/ 18 апреля 2010

Хорошо, на этот раз я решил составить список с использованием STL.Мне нужно создать выделенный сокет TCP для каждого клиента.Поэтому каждый раз, когда у меня есть соединение, я создаю экземпляр сокета и добавляю указатель на него в списке.

list<MyTcp*> SocketList;  //This is the list of pointers to sockets
list<MyTcp*>::iterator it;  //An iterator to the list of pointers to TCP sockets.

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

it=SocketList.begin();
while( it != SocketList.end() ){
    if((*it)->getClientId() == id){
    pSocket = it; //    <-------------- compiler complains at this line
    SocketList.remove(pSocket);
    pSocket->Disconnect();
    delete pSocket;
    break;
    }
}

Но компилятор говорит это:

 error: invalid cast from type ‘std::_List_iterator<MyTcp*>’ to type ‘MyTcp*’

Может кто-нибудь помочь мне здесь?я думал, что все делал правильно, разве итератор в любой момент времени просто указывает на один из элементов набора?как я могу это исправить?

Ответы [ 4 ]

18 голосов
/ 18 апреля 2010

Попробуйте это:

pSocket = *it; 

Итераторы во многом действуют как указатели, но на самом деле они могут быть указателями или полноценными классами, действующими как один. В этом случае важно то, что когда вы разыменовываете один, вы получаете все, что хранится в контейнере. Так как вы храните MyTcp* s в списке, при разыменовании итератора вы получаете MyTcp*. pSocket имеет тип MyTcp*, поэтому приведенное выше задание выполнено успешно. Назначение, которое вы пытаетесь выполнить, не разыменовывает итератор - вы пытаетесь присвоить самому итератору значение pSocket.

Это похоже на следующий случай:

void foo()
{
    MyTcp *array[10]; // An array full of MyTcp pointers
    MyTcp **iterator = NULL; // pointers make good iterators for arrays (but not for std::lists)
    for (iterator = array; iterator != array + 10; ++iterator)
    {
        // This fails to compile (cannot assign MyTcp** to MyTcp*:
        MyTcp *wrong = iterator;            

        // This succeeds:
        MyTcp *current = *iterator; // important to dereference the iterator
    }
} 
6 голосов
/ 18 апреля 2010

Итератор - это обобщение указателя. В Википедии есть хорошая статья об Итераторе.

Причина, по которой итераторы используются в STL, заключается в создании алгоритмов, ортогональных к контейнерам. Любой контейнер можно использовать с (почти) любым алгоритмом, если этот контейнер поддерживает итераторы.

4 голосов
/ 18 апреля 2010

Итератор может быть реализован указателем (в случае вектора это так). Итераторы имеют семантику указателей - вы обращаетесь к ним, чтобы получить значение.

Но вы храните указатели в списке. «MyTcp *» - это ваше значение, поэтому, чтобы присвоить его, вы разыменовываете «it».

pSocket = *it;
3 голосов
/ 18 апреля 2010

Итератор просто указывает на один из элементов, и синтаксис для разыменования он тот же, но это другой тип (с другим представлением в памяти), и арифметика указателя на нем делает что-то другое, чем он на указатель (т. е. результат арифметики итератора указывает на другое место в памяти, чем если бы вы преобразовали итератор в указатель и выполнили арифметику указателя), так что вы обычно не хотите путать эти два типа.

Однако, учитывая, что ваш список является списком указателей, и вы только разыменовываете pSocket один раз в вызове pSocket->Disconnect();, я думаю, что ответ Eclipse - то, что вы хотите: pSocket = *it;

...