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

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

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

使用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数组的合法用法。 例如,如果性能绝对至关重要,则堆栈上的小型Carrays可能是比std::string更好的解决方案。 您可能还在编写一个程序,您需要对内存分配/释放进行绝对控制,在这种情况下,您将使用char* 。 另外,正如在注释部分中指出的那样, std::string不能保证为您提供连续的可写缓冲区*,因此如果您需要,则不能直接从文件写入std::string程序完全可移植。 但是,如果您需要这样做, std::vector仍然可能比使用原始C数组更可取。

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

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

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

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

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

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

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

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

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

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

但是对于其他任何事情, std::string隐藏了所有这些的事实使得它更加可用。

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

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

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

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

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

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

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

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

 strlen(infinitelengthstring) 

 string.length() 

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

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

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

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