为什么 std::string 不是 std::vector 的特化?
Why isn't std::string a specialization of std::vector?
将字符串视为字符向量似乎很明显。那么为什么字符串有自己的特殊实现,这似乎与向量的实现大不相同class?
为了说明这一点,这里有一些来自两个 classes 的片段,以表明所需的工作非常相似,例如两者都使用分配器来管理内存。具有特征也可能对向量有用。
下面从 std::string 的实现中截取的片段看起来适合更通用的 std::vector 实现,如果我们允许向量具有类型特征的话。
139 template <class _charT, class _Traits , class _Allocator > |
140 class _RWSTDExportTemplate basic_string |
141 { |
142 public:
....
333 size_type size () const { return length(); } |
334 inline size_type length () const; |
335 size_type max_size () const |
336 { |
337 return npos - sizeof(__rep_type)-2; |
338 } |
339 inline void resize (size_type, _charT); |
340 void resize (size_type n) |
341 { |
342 resize(n,__eos()); |
343 } |
344 inline size_type capacity () const; |
345 inline void reserve (size_type=0); |
346 void clear () { erase(); } |
347 bool empty () const { return length() == 0; }
这是来自矢量:
75 template <class _Tt, class _Allocator _RWSTD_COMPLEX_DEFAULT(allocator<_Tt>) > |
76 class vector |
77 { |
78
86 public: |
87 // |
88 // Types. |
89 // |
90 typedef _Tt value_type; |
91 typedef _Allocator allocator_type; |
92
383 // |
384 // Capacity.
385 //
386 size_type size () const { return size_type(end() - begin()); }
387 size_type max_size () const { return __value_alloc_type(__end_of_storage).max_size(); }
388 void resize (size_type new_size);
389 void resize (size_type new_size, _Tt value);
390
391 size_type capacity () const { return size_type(__end_of_storage.data() - begin()); }
392 bool empty () const { return begin() == end(); }
393 void reserve (size_type n)
394 {
395 _RWSTD_THROW(n > max_size(), length_error,
396 __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
397 "vector::reserve(size_t)",n,max_size()).msgstr());
398
399 if (capacity() < n)
400 {
401 __value_alloc_type va(__end_of_storage);
402 iterator tmp = va.allocate(n,__start);
403#ifndef _RWSTD_NO_EXCEPTIONS
404 try {
405 uninitialized_copy(begin(), end(), tmp);
406 } catch(...) {
407 __value_alloc_type(__end_of_storage).deallocate(tmp,n);
408 throw;
409 }
410#else
以这个片段为例:
string s = "abc";
没有容器具有类似的初始化语法,它接收指向第一个元素的指针并扫描序列以寻找特殊的终止符元素。使用 std::vector
至少会很麻烦。由于文本在计算中很常见,因此拥有方便的文本容器类型是必需的,std::vector
只是不合适。
也就是说,我可以想象 std::string
继承 std::vector<char>
私下或聚合它,但这与它的专业化完全不同。它也不能是一个专业化,因为如果你想要一个不像字符串的 vector<char>
怎么办?然后,您将拥有与今天 vector<bool>
相同的 fubar。
A std::string
的行为与 std::vector
不兼容,尤其是末尾出现零值。
C++11 §21.4.5/2 关于 operator[]
,在 [string.access] 中:
” Returns: *(begin() + pos)
if pos < size()
, otherwise a reference to an object of type T
with value
charT()
; the referenced value shall not be modified.
另一个很大的区别是std::string
支持小缓冲区优化,而那个优化可能性是not available for std::vector
。
将字符串视为字符向量似乎很明显。那么为什么字符串有自己的特殊实现,这似乎与向量的实现大不相同class?
为了说明这一点,这里有一些来自两个 classes 的片段,以表明所需的工作非常相似,例如两者都使用分配器来管理内存。具有特征也可能对向量有用。
下面从 std::string 的实现中截取的片段看起来适合更通用的 std::vector 实现,如果我们允许向量具有类型特征的话。
139 template <class _charT, class _Traits , class _Allocator > |
140 class _RWSTDExportTemplate basic_string |
141 { |
142 public:
....
333 size_type size () const { return length(); } |
334 inline size_type length () const; |
335 size_type max_size () const |
336 { |
337 return npos - sizeof(__rep_type)-2; |
338 } |
339 inline void resize (size_type, _charT); |
340 void resize (size_type n) |
341 { |
342 resize(n,__eos()); |
343 } |
344 inline size_type capacity () const; |
345 inline void reserve (size_type=0); |
346 void clear () { erase(); } |
347 bool empty () const { return length() == 0; }
这是来自矢量:
75 template <class _Tt, class _Allocator _RWSTD_COMPLEX_DEFAULT(allocator<_Tt>) > |
76 class vector |
77 { |
78
86 public: |
87 // |
88 // Types. |
89 // |
90 typedef _Tt value_type; |
91 typedef _Allocator allocator_type; |
92
383 // |
384 // Capacity.
385 //
386 size_type size () const { return size_type(end() - begin()); }
387 size_type max_size () const { return __value_alloc_type(__end_of_storage).max_size(); }
388 void resize (size_type new_size);
389 void resize (size_type new_size, _Tt value);
390
391 size_type capacity () const { return size_type(__end_of_storage.data() - begin()); }
392 bool empty () const { return begin() == end(); }
393 void reserve (size_type n)
394 {
395 _RWSTD_THROW(n > max_size(), length_error,
396 __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
397 "vector::reserve(size_t)",n,max_size()).msgstr());
398
399 if (capacity() < n)
400 {
401 __value_alloc_type va(__end_of_storage);
402 iterator tmp = va.allocate(n,__start);
403#ifndef _RWSTD_NO_EXCEPTIONS
404 try {
405 uninitialized_copy(begin(), end(), tmp);
406 } catch(...) {
407 __value_alloc_type(__end_of_storage).deallocate(tmp,n);
408 throw;
409 }
410#else
以这个片段为例:
string s = "abc";
没有容器具有类似的初始化语法,它接收指向第一个元素的指针并扫描序列以寻找特殊的终止符元素。使用 std::vector
至少会很麻烦。由于文本在计算中很常见,因此拥有方便的文本容器类型是必需的,std::vector
只是不合适。
也就是说,我可以想象 std::string
继承 std::vector<char>
私下或聚合它,但这与它的专业化完全不同。它也不能是一个专业化,因为如果你想要一个不像字符串的 vector<char>
怎么办?然后,您将拥有与今天 vector<bool>
相同的 fubar。
A std::string
的行为与 std::vector
不兼容,尤其是末尾出现零值。
C++11 §21.4.5/2 关于 operator[]
,在 [string.access] 中:
” Returns:
*(begin() + pos)
ifpos < size()
, otherwise a reference to an object of typeT
with valuecharT()
; the referenced value shall not be modified.
另一个很大的区别是std::string
支持小缓冲区优化,而那个优化可能性是not available for std::vector
。