2015-02-09 107 views
7

将字符串视为字符向量似乎很明显。为什么字符串有自己特殊的实现,这与vector类的实现看起来有很大不同?为什么不是std :: string是std :: vector的专门化?

为了说明这一点,下面是两个类的一些片段,以表明所需的工作是非常相似的,例如,两者都使用分配器来管理内存。具有特征也可以用于载体。

从std :: string的实现中剪下来的样子看起来像适合std :: vector的更一般的实现,如果我们允许一个vector有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; } 

这是从向量:

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 – 2015-02-09 20:02:28

+2

'std :: string'允许短字符串优化。 – Zeta 2015-02-09 20:03:53

+0

@Zeta什么是短串优化? – Beginner 2015-02-09 20:08:28

回答

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 2015-02-09 20:07:08

+0

@beginner:对不起,我不能认为那些会使*不可能发生的事情是不可能的。好问题! – 2015-02-09 20:12:15

+0

副题:既然它是重复的:我应该删除这个问题吗? – Beginner 2015-02-09 20:13:38

3

采取例如这个片段:

string s = "abc"; 

没有容器具有相似类型初始化语法那里它接收一个指针到第一个元素并扫描特殊终止符元素的序列。至少使用std::vector会很麻烦。由于文本在计算中很常见,因此拥有方便的文本容器类型仅仅是必需的,并且不适合。

也就是说,我可以想象std::string私人地继承std::vector<char>或聚合它,但这是一个完全不同的问题,而不是专业化的问题。它也不可能是专业化的,因为如果你想要一个vector<char>那不像一个字符串?然后您将拥有与今天的vector<bool>相同的fubar。

+0

这可以通过赋值操作符完成,或者不完成? – Beginner 2015-02-09 20:15:20

+0

你提到的“this”究竟是什么? – 2015-02-09 20:36:12

+0

开头的代码片段:这可以通过将char数组赋值给具有赋值运算符的矢量来完成。 – Beginner 2015-02-09 20:38:04

相关问题