取消或减少随机访问迭代器指向开始

时间:2011-12-16 12:04:18

标签: c++ iterator decrement

考虑以下代码

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()不能在地址0内部指向内存,我认为它是结束,但所有容器都依赖于标准的alocator。该alocator依赖于new运算符。此外,没有new永远不会返回0的信息。但是标准的alocator也依赖于delete运算符,如果你传递0,这个运算符就不会做任何事情。因此,new无法返回0,因为无法删除该指针,因此非空vector无法返回begin()指向0

结论:

如果上面是正确递减的交互者,那么指向vector::begin()应该是安全的,因为vector的内部记忆是持续存在的。

我是对的吗?

终极答案

即使它现在有效并将在未来工作,它仍然是根据标准未定义的行为。如果你这样做,你自己承担风险。有关更多信息,请参阅此类似 question

1 个答案:

答案 0 :(得分:6)

你不能减少传递开始的迭代器,或者计算begin() - 1

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


问题2:

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

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

在解除分配的空间之后开始的另一个内存块可能会有一个地址,比如0x10000,其中地址0x10000 - 1不再存在。一些使用专用地址寄存器指针的硬件在加载无效指针时会被捕获。只是可以检测到0x10000 - 1不再映射到RAM并中止您的程序。编写标准是为了允许这样做,因为存在这样的硬件。

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

相关问题