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 有什么用处 @vBx 现在你看到***.com/questions/4761529/… 它们是不同的容器。它们可能有很多相似之处,但仅此而已。尝试调用 std::vector&lt;char&gt; 对象的 c_str() 成员。 在内部它们都是chars 的动态数组,但是它们的界面是完全不同的。看看en.cppreference.com/w/cpp/string/basic_string 和en.cppreference.com/w/cpp/container/vector。 string 在向量末尾保留一个额外的字节,该字节始终设置为 0。当您调用 size() 时,它不包括该字节。但是,它存在于c_str() 运算符中,因此它不必在每次调用 c_str 时复制数据。 【参考方案1】: vector&lt;char&gt; 为您提供&amp;v[0]+n == &amp;v[n] 的保证,而字符串没有(实际上是这样,但不能保证)...AFAIK C++0x 已经提供了该保证 没有从const char*vector&lt;char&gt; 的隐式转换 字符串不是 STL 容器。例如,它没有 pop_back()back() 函数 最后但同样重要的是,不同的成员函数! String 为您提供适用于字符串的函数,例如使用 c_str() 返回一个以 null 结尾的字符串

底线:当您需要对字符串进行操作时,请使用string。当你需要一个......好吧,单个字符的向量时,请使用vector&lt;char&gt;......

vector&lt;char&gt; 的另一种用法是避免vector&lt;bool&gt; 特化。

【讨论】:

好的,谢谢@Armen。那么二进制数据呢,我可以把它保存在字符串中吗?这将适用于所有平台str += "\01512";吗? @Mihran:那个二进制文件怎么样?它会将您提到的字符附加到字符串 但它不能以错误的方式从右操作数“\01512”生成字符串(即空字符串,因为文字以\0开头)然后将这个空字符串连接到我们的str 有一个字符串构造函数,它采用字符串的开始和结束迭代器,即使该字符串中嵌入了空字符,它也会遵守该长度。 std::string 操作也将嵌入的 null 视为字符串的一部分。问题是当您将字符串传递给其他使用它的对象时,就像 C 字符串一样。 C++11 添加了pop_back()back() 等。【参考方案2】:

std:string 用于字符串表示,并具有特定于字符串操作的方法,例如substrcompare

您还有c_str 方法,该方法将返回指向有效“C 字符串”的指针,您可以将其用作仅以const char* 作为参数的函数的参数,因为它可以保证返回的字符串以零结尾。

std::vector&lt;char&gt; 将只是一个字符数组,最大的问题是因为你没有 c_str 方法,所以你不能将它作为参数传递给采用 const char * 的函数,除非你照顾始终在向量的末尾保持 0。

【讨论】:

类似substr的函数也存在于向量中,即std::copy 是的,但它们不是成员函数,例如 substr。我也可以将 std::copy 与 std::string 一起使用。【参考方案3】:

std::vector&lt;char&gt; 可以像 std::string 一样使用,但反过来则不然。

std::vector&lt;char&gt; 只存储字符序列,但并非所有字符序列都是字符串。考虑二进制数据,它将正确存储在std::vector&lt;char&gt;(或std::vector&lt;unsigned char&gt;)中;将其存储在字符串中是没有意义的。

在内部,std::string 可以以与 std::vector&lt;char&gt; 大致相同的方式实现——实际上,您可以将其视为概念上相同的方式——但在实践中,有几个重要的区别:

    C++11 introduced the requirement that a std::string is required to store a NUL-terminated sequence of characters internally。这使其合规,并使与 C 样式字符串的互操作更容易。显然,std::vector&lt;char&gt; 不会有与它相关联的要求,您也不希望它有。

    std::stringstd::vector&lt;&gt; 相比提供了一个非常不同且扩展了很多的界面。虽然后者只是一个无聊的旧元素序列,但前者实际上是为表示一个字符串而设计的,因此提供了各种与字符串相关的便利功能。 (有些人会争辩 too many,宁愿这些作为独立的“免费”函数实现,而不是特殊“字符串”类的成员函数。)

    std::string 的常见实现将使用称为"small string optimization (SSO)" 的优化,当您存储直接适合std::string 对象实例的字符串时,它可以避免动态内存分配。在std::vector&lt;&gt;(尽管it could actually be implemented in a custom vector type)中找不到这种优化。

    而且,为了启用小字符串优化,标准要求交换 std::string 使其迭代器无效。该要求不适用于std::vector&lt;&gt;

    虽然现在可能只是历史上的好奇心(特别是因为在实践中几乎没有标准库的实现以这种方式工作),但在 C++03 和以前版本的语言标准中,std::string 不是 em> 需要将字符串中的字符存储在连续内存中。换句话说,它实际上不必作为数组的包装器来实现。这允许在后台使用 rope data structure 和/或写时复制策略之类的东西。 std::vector&lt;&gt; 总是需要对其元素进行连续存储。 (C++11 对std::string 引入了同样的要求。)

【讨论】:

【参考方案4】:

std::string 针对典型的字符串处理操作进行了优化,参见例如http://www.cplusplus.com/reference/string/string/“字符串操作”的最后一段。

std::vector 是任何类型数据的通用容器,不仅是字符,因此对于人们通常只对字符串执行的操作没有特定的支持。

用于处理字符串的函数通常支持string,但不支持vector&lt;char&gt;

【讨论】:

我不是在问什么是 std::string 和什么是 std::vector. 如果您的数据代表一段文本,请使用string,因为它是为此目的而创建的,并且支持人们通常对文本执行的操作。但你当然知道这一点。你的问题我不清楚。【参考方案5】:

为什么要比较这些不同的数据类型? std::string 是一个库,提供如下简单的字符串处理:

std::string myString;
myString = "My Funny Text";
size_t startOfFunny = myString.find("Funny");

std::vector 没有字符串操作函数,因为它只是一种容器。如果您需要彼此独立地存储chars,您可以使用它。

【讨论】:

以上是关于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