问题描述
请考虑以下代码段
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.
这篇关于抽象或减少随机访问迭代器指向开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!