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

Beg*_*End 1 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,有一些疑问,因为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是连续的.

我对吗?

终极答案

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

Bo *_*son 6

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

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


关于问题2:

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

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

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

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

  • @beginend:如果你的向量包含100byte对象,并且向量从地址4开始怎么办?Begin() - 1会下溢.在开始之前有一个迭代器是未定义的.期. (3认同)