让我们想象一下你很富有(也许你是或者你不是......无论如何)!
既然你很富有,你就可以在茉莉雅岛(法属波利尼西亚向风群岛)购买一块土地。你很确定这是一个不错的房产,所以你在那个岛上建了一座别墅,然后住在那里。你的别墅有一个游泳池、一个网球场、一个大车库,还有更多好东西。
一段时间后,您会离开茉莉雅岛,因为您认为它变得非常无聊。运动多,但人少。你卖掉了你的土地和别墅,并决定搬到其他地方。
如果您稍后再回来,您可能会遇到很多不同的事情,但您甚至无法确定其中之一。
- 你的别墅可能会消失,取而代之的是俱乐部酒店。
- 你的别墅可能还在。
- 该岛可能会沉没。
- ...
谁知道?即使别墅可能不再属于您,您甚至可以再次跳入游泳池或打网球。旁边可能还有另一栋别墅,您可以在更大的游泳池中游泳,而不会分散您的注意力。
如果你再次回来,你无法保证你会发现什么,这与你的向量相同,它在我看过的实现中包含三个指针:(名称可能不同,但功能大多相同.)
begin
指向分配的内存位置(即X)的开始
end
指向分配内存的末尾+1(即开始+4)
last
它指向容器中的最后一个元素+1(即begin+4)
通过调用 clear 容器可以很好地销毁所有元素并重置last = begin;
。该函数size()
很可能会return last-begin;
出现,因此您会观察到容器大小为 0。尽管如此,begin
它可能仍然有效并且可能仍然分配了内存(end
可能仍然是begin+4
)。您甚至可以观察到您在 clear() 之前设置的值。
std::vector<int> a(4);
a[2] = 12;
cout << "a cap " << a.capacity() << ", ptr is " << a.data() << ", val 2 is " << a[2] << endl;
a.clear();
cout << "a cap " << a.capacity() << ", ptr is " << a.data() << ", val 2 is " << a[2] << endl;
印刷:
上限 4,ptr 为 00746570,val 2 为 12
上限 4,ptr 为 00746570,val 2 为 12
为什么你没有观察到任何错误?这是因为std::vector<T>::operator[]
不执行任何越界检查(与之相反std::vector<T>::at()
)。由于 C++ 不包含“段错误”,您的程序似乎可以正常运行。
注意:如果在调试模式下编译,MSVC 2012operator[]
会执行边界检查。
欢迎来到未定义行为的土地!事情可能发生也可能不会发生。您甚至可能无法对单一情况有所了解。您可以冒险并足够大胆地研究它,但这可能不是生成可靠代码的方式。