C ++ std :: vector和std :: basic_string之间的根本区别是什么?
答案 0 :(得分:19)
basic_string不调用其元素的构造函数和析构函数。矢量呢。
交换basic_string使迭代器无效(启用小字符串优化),交换向量不会。
在C ++ 03中不能连续分配basic_string内存。矢量总是连续的。在C ++ 0x [string.require]:
中删除了这种差异basic_string对象中的类char对象应连续存储
basic_string具有字符串操作的接口。矢量没有。
basic_string可以在写策略上使用copy(在C ++ 11之前)。矢量不能。
非信徒的相关引言:
[basic.string]:
类模板basic_string符合序列容器(23.2.3)的要求 可逆容器(23.2),以及可识别分配器的容器(表99),但basic_string除外 不使用allocator_traits :: construct和allocator_-构造或销毁其元素 traits :: destroy和basic_string的swap()使迭代器无效。支持的迭代器 by basic_string是随机访问迭代器(24.2.7)。
答案 1 :(得分:12)
basic_string
提供编译器和标准库实现,对vector的一些自由:
“小字符串优化”对字符串有效,允许实现在字符串短时在字符串对象中存储实际字符串,而不是指向字符串的指针。有点像:
class string
{
size_t length;
union
{
char * usedWhenStringIsLong;
char usedWhenStringIsShort[sizeof(char*)];
};
};
在C ++ 03中,底层数组不需要是连续的。根据现行标准,在“绳索”等方面实施basic_string
是可能的。 (虽然没有人这样做,因为这会使成员std::basic_string::c_str()
和std::basic_string::data()
实施成本太高。)
C ++ 11现在禁止这种行为。
在C ++ 03中,basic_string
允许编译器/库供应商对数据使用copy-on-write(可以保存副本),{{1}不允许这样做}。在实践中,这曾经是更常见的,但现在不太常见,因为它对多线程有影响。无论哪种方式,您的代码都不能依赖于std::vector
是否使用COW实现
C ++ 11现在再次禁止这种行为。
std::basic_string
也有一些辅助方法,但大多数都很简单,当然可以在basic_string
之上轻松实现。
答案 2 :(得分:6)
关键区别在于std::vector
无法将std::basic_string
数据保存在连续内存中。结果:
std::vector<char> v( 'a', 3 );
char* x = &v[0]; // valid
std::basic_string<char> s( "aaa" );
char* x2 = &s[0]; // doesn't point to continuous buffer
//For example, the behavior of
std::cout << *(x2+1);
//is undefined.
const char* x3 = s.c_str(); // valid
答案 3 :(得分:0)
向量是模拟数组的数据结构。它内部深处实际上是一个(动态)数组。
basic_string类表示一个字符序列。它包含Sequence的所有常用操作,此外,它还包含标准字符串操作,如搜索和连接。
您可以使用向量来保留您想要的任何数据类型std::vector<int> or <float> or even std::vector< std::vector<T> >
,但basic_string
只能用于表示“文本”。
答案 4 :(得分:0)
basic_string提供了许多特定于字符串的比较选项。你是正确的,因为底层的内存管理接口非常相似,但字符串包含许多额外的成员,比如c_str(),这对于一个向量没有意义。
答案 5 :(得分:0)
std::string
和std::vector
之间的一个区别是,程序可以从以null结尾的字符串构造一个字符串,而使用矢量则不能。
std::string a = "hello"; // okay
std::vector<char> b = "goodbye"; // compiler error
这通常使字符串更易于使用。
答案 6 :(得分:0)
string
被优化为仅包含字符基元,vector
可以包含基元或对象 vector
和string
之间的一个显着差异是vector
可以正确包含对象,string
仅适用于基元。所以vector
提供的这些方法对于使用基元的string
来说是无用的:
即使扩展string
也不允许它正确处理对象,因为它缺少析构函数。这不应该被视为一个缺点,它允许vector
中的string
进行重大优化:
char_traits
模板参数之一string
来定义应如何对包含的基元实施操作(仅包含char
,wchar_t
,{已实施{1}}和char16_t
:http://en.cppreference.com/w/cpp/string/char_traits)特别相关的是char_traits::copy
,char_traits::move
和char_traits::assign
,显然意味着将使用直接赋值,而不是构造或破坏,这对于原语来说更可取。所有这些专业化都有char32_t
的额外缺点:
string
,char
,wchar_t
或char16_t
基元类型。显然,大小不超过32位的基元,可以使用等效大小的char32_t
:https://stackoverflow.com/a/35555016/2642059,但对于诸如char_type
之类的基元来说,long long
的新特性{ {1}}需要编写,专门设计char_traits::eof
和char_traits::not_eof
而不仅仅使用char_traits
的想法似乎不是最好的时间用途。vector<long long>
迭代器无效的操作都会使迭代器失效,但string::swap
和string::operator=
<vector
迭代器会使string
迭代器失效。 / LI>
醇>
vector
和string
的接口的其他差异:
string::data
:Why Doesn't std::string.data() provide a mutable char*? string
提供了处理vector
中不可用字词的功能:string::c_str
,string::length
,string::append
,string::operator+=
,{{3} },string::compare
,string::replace
,string::substr
,string::copy
,string::find
,string::rfind
,string::find_first_of
,string::find_first_not_of
, string::flind_last_of
,string::find_last_not_of
,string::operator+
,string::operator>>
,string::operator<<
,string::stoi
,string::stol
,string::stoll
,{{ 3}},string::stoul
,string::stoull
,string::stof
,string::stod
,string::stold
vector
接受另一个vector
的参数,string
接受string
或一个char*
请注意,这个答案是针对C ++ 11编写的,因此需要连续分配string
。