std::string 和 std::vector<char> 有啥区别?
Posted
技术标签:
【中文标题】std::string 和 std::vector<char> 有啥区别?【英文标题】:What are differences between std::string and std::vector<char>?std::string 和 std::vector<char> 有什么区别? 【发布时间】:2011-07-01 12:26:04 【问题描述】:那么主要区别是什么?在哪些情况下会用到它们?
【问题讨论】:
我看不出 std::vector 有什么用处std::vector<char>
对象的 c_str()
成员。
在内部它们都是char
s 的动态数组,但是它们的界面是完全不同的。看看en.cppreference.com/w/cpp/string/basic_string 和en.cppreference.com/w/cpp/container/vector。
string
在向量末尾保留一个额外的字节,该字节始终设置为 0。当您调用 size()
时,它不包括该字节。但是,它存在于c_str()
运算符中,因此它不必在每次调用 c_str 时复制数据。
【参考方案1】:
vector<char>
为您提供&v[0]+n == &v[n]
的保证,而字符串没有(实际上是这样,但不能保证)...AFAIK C++0x 已经提供了该保证
没有从const char*
到vector<char>
的隐式转换
字符串不是 STL 容器。例如,它没有 pop_back()
或 back()
函数
最后但同样重要的是,不同的成员函数! String 为您提供适用于字符串的函数,例如使用 c_str()
返回一个以 null 结尾的字符串
底线:当您需要对字符串进行操作时,请使用string
。当你需要一个......好吧,单个字符的向量时,请使用vector<char>
......
vector<char>
的另一种用法是避免vector<bool>
特化。
【讨论】:
好的,谢谢@Armen。那么二进制数据呢,我可以把它保存在字符串中吗?这将适用于所有平台str += "\01512";
吗?
@Mihran:那个二进制文件怎么样?它会将您提到的字符附加到字符串
但它不能以错误的方式从右操作数“\01512”生成字符串(即空字符串,因为文字以\0开头)然后将这个空字符串连接到我们的str
?
有一个字符串构造函数,它采用字符串的开始和结束迭代器,即使该字符串中嵌入了空字符,它也会遵守该长度。 std::string 操作也将嵌入的 null 视为字符串的一部分。问题是当您将字符串传递给其他使用它的对象时,就像 C 字符串一样。
C++11 添加了pop_back()
和back()
等。【参考方案2】:
std:string
用于字符串表示,并具有特定于字符串操作的方法,例如substr
和compare
。
您还有c_str
方法,该方法将返回指向有效“C 字符串”的指针,您可以将其用作仅以const char*
作为参数的函数的参数,因为它可以保证返回的字符串以零结尾。
std::vector<char>
将只是一个字符数组,最大的问题是因为你没有 c_str
方法,所以你不能将它作为参数传递给采用 const char *
的函数,除非你照顾始终在向量的末尾保持 0。
【讨论】:
类似substr
的函数也存在于向量中,即std::copy
。
是的,但它们不是成员函数,例如 substr。我也可以将 std::copy 与 std::string 一起使用。【参考方案3】:
std::vector<char>
可以像 std::string
一样使用,但反过来则不然。
std::vector<char>
只存储字符序列,但并非所有字符序列都是字符串。考虑二进制数据,它将正确存储在std::vector<char>
(或std::vector<unsigned char>
)中;将其存储在字符串中是没有意义的。
在内部,std::string
可以以与 std::vector<char>
大致相同的方式实现——实际上,您可以将其视为概念上相同的方式——但在实践中,有几个重要的区别:
C++11 introduced the requirement that a std::string
is required to store a NUL-terminated sequence of characters internally。这使其合规,并使与 C 样式字符串的互操作更容易。显然,std::vector<char>
不会有与它相关联的要求,您也不希望它有。
std::string
与std::vector<>
相比提供了一个非常不同且扩展了很多的界面。虽然后者只是一个无聊的旧元素序列,但前者实际上是为表示一个字符串而设计的,因此提供了各种与字符串相关的便利功能。 (有些人会争辩 too many,宁愿这些作为独立的“免费”函数实现,而不是特殊“字符串”类的成员函数。)
std::string
的常见实现将使用称为"small string optimization (SSO)" 的优化,当您存储直接适合std::string
对象实例的字符串时,它可以避免动态内存分配。在std::vector<>
(尽管it could actually be implemented in a custom vector type)中找不到这种优化。
而且,为了启用小字符串优化,标准要求交换 std::string
使其迭代器无效。该要求不适用于std::vector<>
。
虽然现在可能只是历史上的好奇心(特别是因为在实践中几乎没有标准库的实现以这种方式工作),但在 C++03 和以前版本的语言标准中,std::string
不是 em> 需要将字符串中的字符存储在连续内存中。换句话说,它实际上不必作为数组的包装器来实现。这允许在后台使用 rope data structure 和/或写时复制策略之类的东西。 std::vector<>
总是需要对其元素进行连续存储。 (C++11 对std::string
引入了同样的要求。)
【讨论】:
【参考方案4】:std::string
针对典型的字符串处理操作进行了优化,参见例如http://www.cplusplus.com/reference/string/string/“字符串操作”的最后一段。
std::vector
是任何类型数据的通用容器,不仅是字符,因此对于人们通常只对字符串执行的操作没有特定的支持。
用于处理字符串的函数通常支持string
,但不支持vector<char>
。
【讨论】:
我不是在问什么是 std::string 和什么是 std::vectorstring
,因为它是为此目的而创建的,并且支持人们通常对文本执行的操作。但你当然知道这一点。你的问题我不清楚。【参考方案5】:
为什么要比较这些不同的数据类型? std::string
是一个库,提供如下简单的字符串处理:
std::string myString;
myString = "My Funny Text";
size_t startOfFunny = myString.find("Funny");
std::vector
没有字符串操作函数,因为它只是一种容器。如果您需要彼此独立地存储char
s,您可以使用它。
【讨论】:
以上是关于std::string 和 std::vector<char> 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
创建 boost::tuple<std::string, std::string, int> 和 std::vector<int> 的映射
用 std::vector<std::string> 替换命令行参数 int argc 和 char** argv
std::vector<std::string> 到 char* 数组
从 Go 中迭代`std::vector<std::string>`?
错误使用 std::vector<std::string> myString
在 std::vector<std::string> 上使用 find_if 和 bind2nd 和 string::compare