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或computebegin()-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
(包括
)来计算需要进行的迭代次数并更改