抽象或减少随机访问迭代器指向开始 [英] Substraction or decrement random access iterator pointing to begin

查看:121
本文介绍了抽象或减少随机访问迭代器指向开始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码段

  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;
}
}

正如你所看到的, c $ c> forward == false 因为有一个从 begin()和迭代器 $ c>可以减去当它指向 begin()



EDIT



我读了ISO C ++标准并有一些结论。
没有承诺 vector :: begin()不能内部指向内存在地址 0 ,我认为这是结束,但所有容器依赖于标准的定位器。这个定位器依赖于 new 运算符。此外,没有任何信息表明 new 永远不会返回 0 。但是标准的alocator也依赖于 delete 运算符,如果你传递 0 ,这个运算符是无效的。所以通过这个事实, new 不能返回 0 因为没有办法删除那个指针,非空向量不能返回 begin()指向 0



结论



指向 vector :: begin()的程序应该是安全的,因为向量的内部存储器是连续的。 / p>

我是对吗?



终止答案



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

解决方案

您不能递减一个迭代器传递begin或计算 begin / code>。



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






在问题2上:



即使 if(p == 0)测试指针是否为空,这不意味着空指针必须由所有位零表示。它也可以是所有位1,或其他。



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



另一个刚好在释放空间之后的内存块可以有一个地址,例如 0x10000 code> 0x10000 - 1 不再存在。一些使用专用地址寄存器用于指针的硬件被称为在加载无效指针时陷阱。只是可以检测到 0x10000 - 1 不再映射到RAM,并中止您的程序。



我们不是说这是通常在普通台式机操作系统上发生的情况,可以根据语言标准发生。


Consider following piece of code

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;
    }
}

As you can see there is some doubt when forward == false becouse there is an substraction from begin() and iterator it can be substracted when it points at begin(). I can't find anywhere if it is ok until I not dereference this bad pointing iterator).

EDIT

I read ISO C++ Standard and have some conclusions. There is no promise that vector::begin() can't internaly point to memory at adress 0, and I was thinking that It is the end, but all containers depend on standard alocator. This alocator depends on new operator. And also, there is no information that new will never return 0. But standard alocator depends also on delete operator and this operator is supose to do nothing if you pass 0. So by this fact, new can't return 0 becouse there will be no way to delete that pointer, and by that, non empty vector can't return begin() that points to 0.

Conclusion:

If above is right decrementing interator that points at vector::begin() should be safe, since internal memory of the vector is continouse.

Am I right?

ULTIMATE ANSWER

Even if it works now and will be working in the future it is undefined behavour according to the standard. If you do this, you are doing this on your own risk. See this simmilar question for more informations.

解决方案

You cannot decrement an iterator passed begin, or compute begin() - 1.

While the implementation is required to have a position for one passed the last element, it is not required to have any address space available before begin. So begin() - 1 might not be a valid address (and definitely not a valid iterator).


On question number 2:

Even though if (p == 0) tests if the pointer is null, that doesn't mean that a null pointer has to be represented by all bits zero. It could also be all bits 1, or something else. Compiler magic will make the test work anyway.

Another example of an invalid address is that when you deallocate a large block of memory, the heap manager just could possibly also remove the corresponding virtual address space from your process.

Another memory block starting just after the deallocated space could then have an address, say, 0x10000 where the address 0x10000 - 1 does no longer exist. Some hardware, which uses dedicated address registers for pointers, is known to trap when loading an invalid pointer. It just could detect that 0x10000 - 1 isn't mapped to RAM anymore and abort your program. The standard is written to allow this, because such hardware exists.

We don't say that this is what normally happens on common desktop operating systems, just what could happen according to the language standard.

这篇关于抽象或减少随机访问迭代器指向开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆