STL deque容器不支持通过指针偏移读取元素(cplusplus.com意见反馈)
Apr 15, 2014
问题反馈过程 #
http://www.cplusplus.com 是介绍标准c++语言的一个权威网站,在其对deque容器的介绍中,有这样一句(反馈后现已更改):
But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations, thus not allowing direct access by offsetting pointers to elements.
意思是deque容器与vector容器不同,它不保证将元素的存储在连续的内存区域内,所以不能通过指针的偏移去访问数据。
我在Visual Studio 中编写了如下的代码:
deque<int> d;
d.push_back(3);
d.push_front(2);
d.push_front(1); //d: 1 2 3
deque<int>::iterator it;
it = d.begin();
cout<<*it<<endl; //1
cout<<*(it+1)<<endl; //2 access by offset
最后一行中,我可以通过对it加上偏移1,实现元素访问。 于是我就对原文中那句话产生了疑问。随后我给网站反馈了这点。不久之后,就收到了网站管理员给我的回复。
问题的理解 #
原文中使用的是pointer,实际指的是真实的指针,不包括迭代器iterator。所以不能使用实际指针的偏移去访问元素,因为内存是不连续的,但是迭代器就不存在这个问题。其次,使用指针偏移不是就一定会出错,网站原文表述的也准确。
为了更好的理解这个问题,需要了解deque容器的内部实现方式: deque容器的实现实际上采用的确实不是连续存储,它将元素存放在不同的内存块中,每块内存块内的元素是连续存放的,再通过一个索引结构指向这些内存块的地址,形成了两层的结构。这种实现方式,就是为了提供更高效的头部和尾部操作。但是其内存确实不连续,使用指针的偏移可能会出错(注意:是可能会出错,如果偏移量小,在一个内存块中,则不会出错,如果超过了一个内存块,则必然出错)。
问题的解决 #
管理员对我反馈的那句话已经进行了更改,现在的说法更准确清晰。
But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations: accessing elements in a deque by offsetting a pointer to another element causes undefined behavior.