为什么在C ++中更喜欢char *而不是string?

时间:2009-11-19 15:26:17

标签: c++ c string

我是一名试图编写c ++代码的C程序员。我听说C ++中的string在安全性,性能等方面优于char*,但有时似乎char*是更好的选择。有人建议程序员不要在C ++中使用char*,因为我们可以做char*可以用字符串做的所有事情,而且它更安全,更快。

您曾在C ++中使用过char*吗?具体条件是什么?

12 个答案:

答案 0 :(得分:27)

使用std::string更安全,因为您不必担心为字符串分配/释放内存。 C ++ std::string类可能在内部使用char*数组。但是,该类将为您管理内部数组的分配,重新分配和释放。这消除了使用原始指针带来的所有常见风险,例如内存泄漏,缓冲区溢出等。

此外,它也非常方便。您可以复制字符串,附加到字符串等,而无需手动提供缓冲区空间或使用strcpy / strcat等函数。使用std :: string,就像使用=+运算符一样简单。

基本上,它是:

 std::string s1 = "Hello ";
 std::string s2 = s1 + "World";

...对比

 const char* s1 = "Hello";
 char s2[1024]; // How much should I really even allocate here?
 strcpy(s2, s1);
 strcat(s2, " World ");

修改

回应您关于在C ++中使用char*的编辑:许多C ++程序员声称您从不使用char*,除非您正在使用某些API /需要它的遗留函数,在这种情况下,您可以使用std::string::c_str()函数将std::string转换为const char*

但是,我想说在C ++中有一些C数组的合法用法。例如,如果性能绝对至关重要,则堆栈上的小型C阵列可能是比std::string更好的解决方案。您可能还在编写一个需要绝对控制内存分配/释放的程序,在这种情况下,您将使用char*。另外,正如评论部分所指出的,std::string不能保证为您提供连续的可写缓冲区*,因此如果您不能直接从文件写入std::string需要你的程序完全可移植。但是,如果您需要执行此操作,std::vector仍可能更适合使用原始C阵列。


*虽然在C ++ 11中这已经改变,所以std::string确实为你提供了一个连续的缓冲区

答案 1 :(得分:5)

好的,自从我第一次回答以来,问题发生了很大变化。

与std :: string相比,Native char数组是内存管理和缓冲区溢出的噩梦。我总是喜欢使用std :: string。

也就是说,由于性能限制,char数组在某些情况下可能是更好的选择(虽然std :: string在某些情况下实际上可能更快 - 先测量!)或禁止在嵌入式环境中使用动态内存,等

答案 2 :(得分:2)

通常,std :: string是一种更简洁,更安全的方法,因为它消除了程序员的内存管理负担。它可能比char *更快的主要原因是std :: string存储字符串的长度。因此,每次要复制,追加等时,您都不需要遍历遍历整个字符数组的工作来查找终止NULL字符。

话虽这么说,你仍然会发现很多使用std :: string和char *混合的c ++程序,或者甚至从头开始编写自己的字符串类。在较旧的编译器中,std :: string是一个内存耗尽,并不一定要尽可能快。随着时间的推移,这已经变得越来越好,但是一些高性能应用程序(例如游戏和服务器)仍然可以从手动调整的字符串操作和内存管理中受益。

我建议从std :: string开始,或者可能为它创建一个包含更多实用函数的包装器(例如,starts_with(),split(),format()等)。如果您发现在对代码进行基准测试时,字符串操作是一个瓶颈,或者使用了太多内存,那么您可以决定是否要接受额外的风险并测试自定义字符串库所需的内容。

提示:解决内存问题并仍然使用std :: string的一种方法是使用嵌入式数据库,例如SQLite。这在生成和操作非常大的字符串列表时特别有用,并且性能优于您的预期。

答案 3 :(得分:1)

C char *字符串不能包含'\ 0'字符。 C ++字符串可以毫无问题地处理空字符。如果用户输入包含\ 0的字符串并使用C字符串,则代码可能会失败。还存在与此相关的安全问题。

答案 4 :(得分:1)

std::string的实现隐藏了您的内存使用情况。如果您正在编写性能关键代码,或者您实际上不得不担心内存碎片,那么使用char *可以为您节省很多麻烦。

除此之外,std::string将所有这些隐藏起来的事实使得它更加实用。

答案 5 :(得分:0)

字符串在性能方面实际上可能更好。还有无数其他原因 - 安全性,内存管理,方便的字符串函数,使std :: string成为无限更好的选择。

编辑:要了解为什么字符串可能更有效,请阅读Herb Sutter的书籍 - 他讨论了一种内部实现字符串的方法,以便将Lazy Initialization与Referencing结合使用。

答案 6 :(得分:0)

使用std::string以获得令人难以置信的便利 - 自动内存处理和方法/操作符。通过一些字符串操作,大多数实现都会进行优化(例如延迟评估几个后续操作 - 节省内存复制)。

如果您需要依赖内存中的特定字符布局进行其他优化,请尝试使用std::vector<char>。如果你有一个非空向量vec,你可以使用char*得到一个&vec[0]指针(向量必须是非空的)。

答案 7 :(得分:0)

简短回答,我没有。例外情况是我使用需要它们的第三方库。在这些情况下,我尝试坚持使用std :: string :: c_str()。

答案 8 :(得分:-1)

比较和对比以下C和C ++示例:

strlen(infinitelengthstring)

string.length()

答案 9 :(得分:-1)

在我的职业生涯中,我有机会只在两个项目中使用std :: string。所有其他人都有自己的字符串类:)

话虽如此,对于新代码,我通常使用std :: string,除了模块边界(由dll /共享库导出的函数),我倾向于暴露C接口并远离C ++类型和问题编译器和std库实现之间的二进制不兼容性。

答案 10 :(得分:-2)

std :: string几乎总是首选。即使对于速度,它在堆栈上使用小数组,然后为更大的字符串动态分配更多。

但是,在许多情况下仍然需要使用char *指针将字符串/数据写入原始缓冲区(例如网络I / O),这不能用std :: string完成。

答案 11 :(得分:-2)

我最近在C ++程序中使用C风格字符串的唯一一次是在需要使用两个C库(当然)专门使用C字符串的项目上。在两种字符串类型之间来回转换使得代码真的很复杂。

我还必须对字符串进行一些操作,这实际上与std :: string有点尴尬,但我不认为在没有上述约束的情况下使用C字符串是一个很好的理由。 / p>