Хорошо на этот раз я решил составить список с помощью 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*’
Кто-то может помочь мне здесь? я думал, что делал вещи правильно, итератор в любой момент времени просто не указывает на один из элементов набора? как я могу зафиксировать его?
Попробуйте следующее:
pSocket = *it;
Итераторы действуют во многом как указатели, но на самом деле они могут быть указатель или полноценный класс, который действует как один. В этом случае важно то, что при разыменовании одного объекта вы получите тот элемент, который хранится в контейнере. Поскольку вы сохраняете в списке MyTcp *
, при разыменовании итератора вы получаете 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
}
}
Итератор может быть реализован с помощью указателя (в случае вектора это так). Итераторы имеют семантику указателя - вы разыменовываете их, чтобы получить значение.
Но вы храните указатели в списке. «MyTcp *» - это ваше значение, поэтому для его присвоения вы разыменовываете «it».
pSocket = *it;
Итератор - это обобщение указателя. В Википедии есть хорошая статья о шаблоне итератора.
Итераторы используются в STL для того, чтобы сделать алгоритмы ортогональными контейнерам. Любой контейнер может использоваться с (почти) любым алгоритмом, если этот контейнер поддерживает итераторы.
Итератор просто указывает на один из элементов, и синтаксис для его разыменования тот же, но это другой тип (с другим представлением в памяти), и арифметика указателя на нем делает что-то другое, чем это делает. на указатель (то есть результат арифметики итератора указывает на другую ячейку памяти, чем вы получили бы, если бы вы преобразовали итератор в указатель и выполнили арифметику указателя), поэтому обычно вы не хотите путать эти два типа.
Однако, учитывая типы, которые ваш список представляет собой список указателей, и вы разыменовываете pSocket
только один раз в вызове pSocket-> Disconnect ();
, я думаю Ответ Eclipse - это то, что вы хотите: pSocket = * it;