Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't std::string a specialization of std::vector? [duplicate]

It seems obvious to consider a string to be a vector of characters. Why then does string have its own special implementation, which seems quite different from that of the vector class?

Just to illustrate the point, here are some snippets from both classes to show that the work needed is rather similar, e.g. both using an allocator to manage memory. Also having traits could be useful for vectors as well.

The following snipped from the implementation of std::string looks like it would fit into the more general implementation of std::vector if we would allow a vector to have type-traits.

 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; }   

And this is from vector:

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
like image 334
Beginner Avatar asked Feb 09 '15 19:02

Beginner


People also ask

What is the difference between std::string and std :: vector?

std::string offers a very different and much expanded interface compared to std::vector<> . While the latter is just a boring old sequence of elements, the former is actually designed to represent a string and therefore offers an assortment of string-related convenience functions.

Is string the same as std::string?

There is no functionality difference between string and std::string because they're the same type.

Why do we use std::string?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

Is std::string contiguous?

A std::string's allocation is not guaranteed to be contiguous under the C++98/03 standard, but C++11 forces it to be. In practice, neither I nor Herb Sutter know of an implementation that does not use contiguous storage.


2 Answers

Take for example this snippet:

string s = "abc";

There is no container that has a similar kind of initialisation syntax where it receives a pointer to the first element and scans the sequence for the special terminator element. Using a std::vector would be cumbersome at least. Since texts are common in computing, having a convenient text container type is simply a necessity and std::vector just doesn't fit.

That said, I could imagine std::string inheriting std::vector<char> privately or aggregating it, but that's a whole different issue than being a specialization of it. It also can't be a specialization, because what if you want a vector<char> that does not behave like a string? You would then have the same fubar as with vector<bool> today.

like image 145
Ulrich Eckhardt Avatar answered Oct 19 '22 04:10

Ulrich Eckhardt


A std::string has behavior that is not compatible with std::vector, in particular the appearance of a zero-value at the end.

C++11 §21.4.5/2 about operator[], in [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.

Another big difference is that std::string supports the small buffer optimization, while that optimization possibility is not available for std::vector.

like image 2
Cheers and hth. - Alf Avatar answered Oct 19 '22 04:10

Cheers and hth. - Alf