C + + 中 string 和 char []类型的区别

对于 C,我们使用 char[]来表示字符串。

对于 C + + ,我看到了使用 std::stringchar数组的示例。

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


int main () {
string name;


cout << "What's your name? ";
getline(cin, name);
cout << "Hello " << name << ".\n";


return 0;
}
#include <iostream>
using namespace std;


int main () {
char name[256];


cout << "What's your name? ";
cin.getline(name, 256);
cout << "Hello " << name << ".\n";


return 0;
}

(两个例子都改编自 http://www.cplusplus.com。)

这两种类型在 C + + 中的区别是什么? (在性能、 API 集成、优缺点等方面)

275156 次浏览

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

就 API 和标准库而言,一切都是用字符串而不是 char []实现的,但是仍然有很多函数从 libc 接收 char [] ,所以你可能需要使用它,除此之外,我总是使用 std: : string。

当然,就效率而言,非托管内存的原始缓冲区在很多情况下几乎总是更快,但是考虑到比较字符串,例如 std: : string 总是有大小来首先检查它,而在 char []中,您需要逐个字符地比较字符。

Arkaitz 正确地认为 string是一种托管类型。对于 来说,这意味着您永远不必担心字符串的长度,也不必担心释放或重新分配字符串的内存。

另一方面,上面例子中的 char[]表示法将字符缓冲区限制为正好256个字符。如果您试图向该缓冲区写入超过256个字符,那么您最多只能覆盖程序“拥有”的其他内存。在最坏的情况下,您将尝试覆盖您不拥有的内存,您的操作系统将立即终止您的程序。

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

我个人认为,除了与旧代码兼容之外,没有任何理由使用 char * 或 char []。String 并不比使用 c-string 慢,只是它会为您处理重新分配。您可以在创建它时设置它的大小,因此如果需要,可以避免重新分配。它的索引操作符([])提供了常量的时间访问(在任何意义上都与使用 c-string 索引器完全相同)。使用 at 方法还可以为您提供检查边界的安全性,这是 c-string 无法做到的,除非您编写它。编译器通常会在发布模式下优化索引器的使用。使用 c-string 很容易,比如 delete vs delete [] ,异常安全,甚至如何重新分配 c-string。

当您必须处理高级概念时,比如拥有 COW 字符串,以及 MT 的非 COW 字符串等,您将需要 std: : string。

如果您担心复制,只要您使用引用和常量引用,那么您将不会因为复制而产生任何开销,这与使用 c-string 所做的事情是一样的。

字符数组就是字符数组:

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

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

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

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

C + + 字符串可以包含嵌入的0个字符,不用计数就知道它们的长度,比堆分配的短文本字符数组更快,并且可以防止缓冲区溢出。另外,它们更易于阅读和使用。


然而,C + + 字符串并不(非常)适合跨 DLL 边界使用,因为这需要任何使用此类 DLL 函数的用户确保使用完全相同的编译器和 C + + 运行时实现,以免他的字符串类的行为不同。

通常,字符串类也会释放调用堆上的堆内存,因此只有在使用共享(。DLL 或者。So)运行时的版本。

简而言之: 在所有内部函数和方法中使用 C + + 字符串。如果你曾经写过。DLL 或者。因此,在公共(dll/so-open)函数中使用 C 字符串。

可以将(char *)看作 string.start ()。本质区别在于(char *)是迭代器,std: : string 是容器。如果你坚持使用基本的字符串,(char *)会给你 std: : string: : iterator 所做的。当您希望获得迭代器的好处以及与 C 的兼容性时,可以使用(char *) ,但这是例外,而不是规则。一如既往,小心迭代器失效。当人们说(char *)不安全时,这就是他们的意思。它和其他 C + + 迭代器一样安全。

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

其中一个区别是 Null 终止(0)。

在 C 和 C + + 中,char * 或 char []将接受一个指向单个 char 的指针作为参数,并将沿着内存跟踪,直到达到0内存值(通常称为 null 终止符)。

C + + 字符串可以包含嵌入的0个字符,不需要计数就可以知道它们的长度。

#include<stdio.h>
#include<string.h>
#include<iostream>


using namespace std;


void NullTerminatedString(string str){
int NUll_term = 3;
str[NUll_term] = '\0';       // specific character is kept as NULL in string
cout << str << endl <<endl <<endl;
}


void NullTerminatedChar(char *str){
int NUll_term = 3;
str[NUll_term] = 0;     // from specific, all the character are removed
cout << str << endl;
}


int main(){
string str = "Feels Happy";
printf("string = %s\n", str.c_str());
printf("strlen = %d\n", strlen(str.c_str()));
printf("size = %d\n", str.size());
printf("sizeof = %d\n", sizeof(str)); // sizeof std::string class  and compiler dependent
NullTerminatedString(str);




char str1[12] = "Feels Happy";
printf("char[] = %s\n", str1);
printf("strlen = %d\n", strlen(str1));
printf("sizeof = %d\n", sizeof(str1));    // sizeof char array
NullTerminatedChar(str1);
return 0;
}

产出:

strlen = 11
size = 11
sizeof = 32
Fee s Happy




strlen = 11
sizeof = 12
Fee