C++ 减法或减法随机访问迭代器指向开始

C++ 减法或减法随机访问迭代器指向开始,c++,iterator,decrement,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();

考虑下面的代码

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;
    }
}
void foo(bool forwad)
{
向量::迭代它,结束它;
int dir;
它=某个全局向量。begin()+某个位置;
如果(转发)
{
dir=1;
it+=1;
end_it=some_global_vector.end();
}
其他的
{
dir=-1;
it-=1;
end\u it=某个全局向量。begin()-1;
}
while(它!=结束它)
{
if(do_domething())
打破
it+=dir;
}
}
正如您所看到的,当
forward==false
时存在一些疑问,因为
begin()
中有一个减法,迭代器
当它指向
begin()
时,它可以被减法。除非我不去引用这个指向错误的迭代器,否则我找不到任何地方它是否正常

编辑

我阅读了ISOC++标准并得出了一些结论。 没有保证
vector::begin()
不能在内部指向地址
0
处的内存,我认为这是结束,但所有容器都依赖于标准alocator。此alocator取决于新的操作员。而且,没有任何信息表明
new
永远不会返回
0
。但是标准的alocator也依赖于
delete
操作符,如果您通过
0
,该操作符将不执行任何操作。因此,根据这一事实,
new
无法返回
0
,因为无法删除该指针,因此,非空的
vector
无法返回指向
0
begin()

结论:

若上面是右递减的,那个么指向
vector::begin()
的interator应该是安全的,因为
vector
的内存是连续的

我说得对吗

最终答案


即使它现在起作用,将来也会起作用,但根据标准,它的行为是未定义的。如果你这样做,你是在冒险。有关更多信息,请参阅此模拟

您不能减少传递给begin的迭代器,也不能计算
begin()-1

虽然实现需要有一个传递到最后一个元素的位置,但在开始之前不需要有任何可用的地址空间。因此
begin()-1
可能不是有效的地址(而且肯定不是有效的迭代器)


关于问题2:

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

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

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


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

您不能减少通过begin或compute
begin()-1的迭代器

虽然实现需要有一个传递到最后一个元素的位置,但在开始之前不需要有任何可用的地址空间。因此
begin()-1
可能不是有效的地址(而且肯定不是有效的迭代器)


关于问题2:

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

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

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


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

对于您的问题,您可能可以将示例代码简化为
vector::iterator it=vec.begin();它--也许您应该重构,以便使用反向迭代器进行反向运动。我可以这样做,如果我不能完成示例中显示的操作,我可能会使用它。您可以使用
std::distance
(包括
)计算需要进行多少次迭代,并将
while
循环更改为
for
循环。就您的问题而言,您可以将示例代码简化为
vector::iterator it=vec.begin();它--也许您应该重构,以便使用反向迭代器进行反向运动。我可以这样做,如果我不能像示例中所示那样做,我可能会使用它。您可以使用
std::distance
(包括
)来计算需要进行的迭代次数并更改