原文:http://blogs.msdn.com/xiangfan/archive/2008/12/04/contiguous-of-stl-containers-and-string.aspx
在C++中,大家都知道vector的数据是连续存放的。下面是标准中的描述(C++03, 23.2.4/1)
The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
这里要注意两点。首先,vector<bool>是特殊的。它针对大小做了优化,bool是压缩存放的。其次,&v[0]当且仅当v.size() > 0时才是有效的操作。
(PS:C++98中并不包含上面的描述。相关历史可以参考:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69)
vector被设计成普通数组的扩展,所以保证数据的连续性便于向底层API传递裸指针。我们可以直接使用v.empty()?NULL:&v[0] (如果你使用默认的allocator,那么operator []的返回值是实际数据的引用,而不是proxy)。
在C++0x中,给vector添加了data成员函数,因此获取数据指针更方便了。
除了vector以外,其它STL容器中的数据就没有连续性的保证了。
string则有所不同。它不是STL容器,标准也没有明确说它的数据是否必须连续存放。不过string同样提供data成员函数,它返回const charT *。下面是该函数在C++03中的定义:
If size() is nonzero, the member returns a pointer to the initial element of an array whose first size() elements equal the corresponding elements of the string controlled by *this
The program shall not alter any of the values stored in the array.
另一方面,标准提到对operator []有:
If pos < size(), returns data()[pos].
因为operator []返回的是引用,对string s,我们有&s[0] == data()。但是,根据上面的黑体字部分,data()是不能修改的。这看上去有点奇怪,因为operator[]返回的引用是可以修改的。
这里是和string数据连续性相关的一个问题:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530
C++0x对这些不明确的地方做了修订,参见n2798.pdf 21.3.1/3:
The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0 <= n < s.size().
C++0x还同时修订了"operator []",它不再依赖于data(在C++0x中,data和c_str的行为是一样的):
If pos < size(), returns *(begin() + pos).
所以,C++0x中,string的数据也保证是连续的,你可以像vector那样将&s[0] (如果s.size() > 0并且你使用默认的allocator)直接传给底层API