C ++中字符串和char []类型之间的区别

时间:2009-08-17 10:52:35

标签: c++ string types

我知道一点C,现在我正在看看C ++。 我习惯使用char数组来处理C字符串,但是当我看到C ++代码时,我看到有使用字符串类型和字符数组的例子:

#include <iostream>
#include <string>
using namespace std;

int main () {
  string mystr;
  cout << "What's your name? ";
  getline (cin, mystr);
  cout << "Hello " << mystr << ".\n";
  cout << "What is your favorite team? ";
  getline (cin, mystr);
  cout << "I like " << mystr << " too!\n";
  return 0;
}

#include <iostream>
using namespace std;

int main () {
  char name[256], title[256];

  cout << "Enter your name: ";
  cin.getline (name,256);

  cout << "Enter your favourite movie: ";
  cin.getline (title,256);

  cout << name << "'s favourite movie is " << title;

  return 0;
}

(来自http://www.cplusplus.com的两个例子)

我认为这是一个广泛问及回答(显而易见的?)问题,但如果有人能告诉我在C ++中处理字符串的两种方式之间究竟有什么区别(性能,API集成,方式,那将是很好的每一个都更好,...)。

谢谢。

6 个答案:

答案 0 :(得分:163)

一个char数组就是 - 一个字符数组:

  • 如果在堆栈上分配(如在您的示例中),它将始终占用例如。 256字节,无论它包含的文本有多长
  • 如果在堆上分配(使用malloc()或new char []),则负责释放内存,并且总是会有堆分配的开销。
  • 如果将超过256个字符的文本复制到数组中,它可能会崩溃,产生丑陋的断言消息或导致程序中其他地方出现无法解释的(错误)行为。
  • 要确定文本的长度,必须逐个字符地扫描数组,以获得\ 0字符。

字符串是一个包含char数组的类,但会自动为您管理它。大多数字符串实现都有一个16个字符的内置数组(因此短字符串不会使堆分段)并使用堆来获取更长的字符串。

您可以像这样访问字符串的char数组:

std::string myString = "Hello World";
const char *myStringChars = myString.c_str();

C ++字符串可以包含嵌入的\ 0字符,知道它们的长度而不计算,比短文本的堆分配字符数组快,并保护您免受缓冲区溢出。此外,它们更易读,更易于使用。

-

但是,C ++字符串不适合跨越DLL边界使用,因为这需要任何具有这种DLL函数的用户来确保他使用完全相同的编译器和C ++运行时实现,以免冒着他的字符串类冒险行为不同。

通常,字符串类也会在调用堆上释放其堆内存,因此如果您使用的是共享(.dll或.so)版本的运行时,它只能再次释放内存。

简而言之:在所有内部函数和方法中使用C ++字符串。如果您曾编写.dll或.so,请在公共(dll / so-exposed)函数中使用C字符串。

答案 1 :(得分:11)

Arkaitz是正确的string是托管类型。这对的意义在于你永远不必担心字符串有多长,也不必担心释放或重新分配字符串的内存。

另一方面,上述情况中的char[]表示法将字符缓冲区限制为正好256个字符。如果您尝试将超过256个字符写入该缓冲区,则最多会覆盖程序“拥有”的其他内存。在最坏的情况下,您将尝试覆盖您不拥有的内存,并且您的操作系统将在现场终止您的程序。

底线?字符串对程序员更友好,char []对计算机来说效率更高。

答案 2 :(得分:6)

嗯,字符串类型是字符串的完全托管类,而char []仍然是C语言中的字符串,表示字符串的字节数组。

就API和标准库而言,一切都是根据字符串而不是char []来实现的,但是仍然有很多来自libc的函数接收char []所以你可能需要将它用于那些,除了我总是使用std :: string。

就效率而言,非托管内存的原始缓冲区对于很多东西几乎总是会更快,但考虑到比较字符串,例如,std :: string总是要先检查它的大小,而使用char []你需要逐个字符地比较。

答案 3 :(得分:5)

我个人认为除了与旧代码的兼容性之外,没有任何理由要使用char *或char []。 std :: string不会比使用c-string慢,除非它会为你处理重新分配。您可以在创建时设置它的大小,从而避免在需要时重新分配。它的索引操作符([])提供了恒定的时间访问(并且在每个意义上都与使用c-string索引器完全相同)。除非你编写它,否则使用at方法可以为你设置检查安全性,这是c-strings无法获得的。您的编译器通常会在发布模式下优化索引器的使用。用c弦很容易弄乱;诸如delete vs delete [],异常安全,甚至如何重新分配c-string。

当你必须处理像COW字符串这样的高级概念,以及MT等非COW时,你需要std :: string。

如果您担心副本,只要您使用引用和const引用,您就不会因副本而产生任何开销,这与您对c-string的操作相同。

答案 4 :(得分:1)

字符串具有辅助函数并自动管理字符数组。您可以连接字符串,对于需要将其复制到新数组的char数组,字符串可以在运行时更改它们的长度。 char数组比字符串更难管理,某些函数可能只接受字符串作为输入,要求您将数组转换为字符串。最好使用字符串,它们是为了不必使用数组而制作的。如果数组客观上更好,我们就不会有字符串。

答案 5 :(得分:0)

将(char *)视为string.begin()。本质区别在于(char *)是一个迭代器,而std :: string是一个容器。如果你坚持使用基本字符串,(char *)会给你std :: string :: iterator的功能。当你想要迭代器的好处以及与C的兼容性时,你可以使用(char *),但这是例外,而不是规则。一如既往,小心迭代器失效。当人们说(char *)不安全时,这就是他们的意思。它和任何其他C ++迭代器一样安全。