1

考虑以下一段代码

void foo( bool forwad )
{
    vector<MyObject>::iterator it, end_it;
    int dir;

    it = some_global_vector.begin() + some_position;
    if( forward )
    {
        dir = 1;
        it += 1;
        end_it = some_global_vector.end();

    }
    else
    {
        dir = -1;
        it -= 1;
        end_it = some_global_vector.begin()-1;
    }

    while( it != end_it )
    {
       if( do_domething() )
         break;

       it += dir;
    }
}

正如您所看到的,当forward == false有一个减法时存在一些疑问,begin()并且迭代器it可以在它指向时被减法begin()。如果可以的话,我找不到任何地方,直到我不取消引用这个错误的指向迭代器)。

编辑

我阅读了 ISO C++ 标准并得出了一些结论。没有承诺vector::begin()不能在内部指向 adress 的内存0,我在想这已经结束了,但是所有容器都依赖于标准分配器。此分配器取决于new运营商。而且,没有new永远不会返回的信息0。但是标准的分配器也依赖于delete操作符,如果你通过了,这个操作符应该什么也不做0。因此,根据这个事实,new不能返回0,因为将无法删除该指针,因此,非空vector不能返回begin()指向0.

结论:

如果上面是正确的递减interator,指向的vector::begin()应该是安全的,因为内部存储器vector是连续的。

我对吗?

终极答案

即使它现在可以工作并且将来可以工作,根据标准,它也是未定义的行为。如果您这样做,您将自行承担风险。有关更多信息,请参阅此类似问题

4

1 回答 1

6

您不能递减传递给 begin 或 compute 的迭代器begin() - 1

虽然实现需要有一个通过最后一个元素的位置,但不需要在开始之前有任何可用的地址空间。所以begin() - 1可能不是一个有效的地址(而且绝对不是一个有效的迭代器)。


关于问题 2:

即使if (p == 0)测试指针是否为空,但这并不意味着空指针必须由所有位为零表示。它也可以是所有位 1,或其他。无论如何,编译器魔术都会使测试工作。

无效地址的另一个示例是,当您释放大块内存时,堆管理器也可能会从您的进程中删除相应的虚拟地址空间。

在释放空间之后开始的另一个内存块可以有一个地址,例如,0x10000该地址0x10000 - 1不再存在。某些硬件使用专用地址寄存器作为指针,在加载无效指针时会陷入陷阱。它只是可以检测到0x10000 - 1不再映射到 RAM 并中止您的程序。编写标准是为了允许这样做,因为存在这样的硬件。

我们并不是说这是常见桌面操作系统上通常会发生的情况,只是根据语言标准可能会发生的情况。

于 2011-12-16T12:11:02.630 回答