【问题标题】:Isn't an Iterator in c++ a kind of a pointer?c++ 中的迭代器不是一种指针吗?
【发布时间】:2011-02-09 07:16:18
【问题描述】:

好吧,这次我决定使用 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*’

有人可以帮我吗?我以为我做对了,在任何给定时间迭代器不只是指向集合中的一个元素吗?我该如何解决?

【问题讨论】:

  • 迭代器指向容器中的一个元素,所以你需要使用 * 操作符取消引用它。
  • 更容易将指针视为一种随机访问迭代器...将所有 RAM 视为一个大向量。

标签: c++ list pointers iterator


【解决方案1】:

试试这个:

pSocket = *it; 

迭代器的行为很像指针,但实际上它们可以是指针或完全成熟的类,就像一个指针一样。在这种情况下,重要的是,当您取消引用一个时,您会得到容器中存储的任何项目。由于您将MyTcp*s 存储在列表中,因此当您取消引用迭代器时,您会得到一个MyTcp*pSocketMyTcp* 类型,所以上面的赋值成功了。您尝试执行的分配不是取消对迭代器的引用——您尝试将迭代器本身分配给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
    }
} 

【讨论】:

  • @Eclipse:[关于指针和迭代器]“当你取消引用一个时,你会得到容器中存储的任何项目......”指针不一样吗? 指针和 C++ 迭代器之间有什么区别吗?
  • @eskay:您可以将指针视为一种迭代器——特别是原始内存上的“随机访问迭代器”。有关该类型迭代器的要求,请参阅sgi.com/tech/stl/RandomAccessIterator.html。不过一般来说,迭代器可以是整个类,在它们的 ++* 运算符中做各种疯狂的事情。请参阅 boost.Iterator (boost.org/doc/libs/1_42_0/libs/iterator/doc/index.html) 了解迭代器真正可以做的一些事情。
  • 只是一个较晚的例子:std::list 本身就是一个双向链表。每个列表元素都单独/独立地存储在堆上的某个位置,因此迭代器需要某种指向当前列表节点的指针。 operator++ 然后不能执行任何类型的简单加法,而是必须将其自己的节点指针设置为指向节点的“下一个”指针指向的值。 (哦,方式,这么多'点'......)所以实际上,它不仅仅是一个指针,而是一个围绕实际指针的整个类(指针应该是唯一必要的数据,所以迭代器和指针的大小应该是一样的)。
【解决方案2】:

迭代器是指针的泛化。 Wikipedia 有一篇关于迭代器模式的好文章。

在 STL 中使用迭代器的原因是使算法与容器正交。只要容器支持迭代器,任何容器都可以与(几乎)任何算法一起使用。

【讨论】:

    【解决方案3】:

    迭代器可能由指针实现(在向量的情况下,它是)。迭代器确实具有指针语义 - 您可以取消引用它们以获取值。

    但是您将指针存储在列表中。 “MyTcp*”是你的值,所以要分配它,你取消引用“it”。

    pSocket = *it;
    

    【讨论】:

      【解决方案4】:

      迭代器确实只是指向其中一个元素,取消引用它的语法是相同的,但它是不同的类型(具有不同的内存表示),并且它的指针算术与它所做的不同在指针上(即迭代器算术的结果指向不同的内存位置,而不是将迭代器转换为指针并进行指针算术),因此您通常不想混淆这两种类型。

      但是,鉴于您的列表是指针列表的类型,并且您仅在 pSocket-&gt;Disconnect(); 调用中取消引用 pSocket 一次,我认为 Eclipse 的答案就是您想要的:pSocket = *it;

      【讨论】:

        猜你喜欢
        • 2017-04-04
        • 2020-04-23
        • 2018-05-30
        • 2014-10-13
        • 2012-02-27
        • 2011-05-22
        • 2018-01-26
        • 2012-12-07
        相关资源
        最近更新 更多