2015-02-09 5 views
7

Кажется очевидным, что строка является вектором символов. Почему же строка имеет свою специальную реализацию, которая кажется совсем иной, чем у векторного класса?Почему не std :: string специализируется на std :: vector?

Просто, чтобы проиллюстрировать суть, приведены некоторые фрагменты из обоих классов, чтобы показать, что требуемая работа довольно схожа, например. оба используют распределитель для управления памятью. Также наличие признаков может быть полезно и для векторов.

Следующие строки из реализации 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 
+1

Исторический дизайн решений. Например: std :: string было разрешено копировать-на-запись, которая была оставлена ​​в C++ 11 –

+2

'std :: string' допускает оп тимизацию коротких строк. – Zeta

+0

@Zeta Что такое оптимизация коротких строк? – Beginner

ответ

2

A std::string имеет поведение, которое несовместимо с std::vector, в частности появление нулевого значения в конце.

C++ 11 §21.4.5/2 о operator[], в [string.access]:

Возвращает: *(begin() + pos), если это pos < size(), в противном случае ссылка на объект типа T со значением charT(); ссылочное значение не должно изменяться.

Еще одна большая разница в том, что std::string поддерживает небольшую оптимизацию буфера, в то время как оптимизация возможность является not available for std::vector.

+0

Не удалось ли это обработать путем добавления нуля при вызове c_str? – Beginner

+0

@beginner: Извините, я не могу думать о чем-то, что * определенно сделало бы это невозможным. Хороший вопрос! –

+0

Боковой вопрос: если это дубликат: я должен удалить вопрос? – Beginner

3

Возьмем для примера сниппета:

string s = "abc"; 

Там нет контейнер, который имеет подобный вид синтаксиса инициализации, где он получает указатель к первому элементу и сканирует последовательность для специального элемента терминатора. Использование std::vector было бы громоздким, по крайней мере. Поскольку тексты являются обычными для вычислений, наличие удобного текстового контейнера является просто необходимым, а std::vector просто не подходит.

Сказанное, я мог представить std::string, наследуя std::vector<char> в частном порядке или агрегируя его, но это совершенно другая проблема, чем специализация. Это также не может быть специализацией, потому что если вам нужен vector<char>, который не ведет себя как строка? Тогда у вас будет тот же фубар, что и у vector<bool>.

+0

Это можно сделать с помощью оператора присваивания или нет? – Beginner

+0

Что именно означает «это», на которое вы ссылаетесь? –

+0

Фрагмент в начале: это можно сделать, назначив массив символов вектору , имеющему оператор присваивания. – Beginner

Смежные вопросы