为什么 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