我使用C风格字符串的唯一原因是与使用C风格字符串的第三方库进行接口交互。也可能会有一些神秘的情况需要出于性能的考虑使用C风格字符串,但更常见的是,由于内联和特化等原因,使用C++字符串上的方法可能更快。
在处理这些类型的API时,您可以在许多情况下使用c_str()
方法,但您应该知道返回的char *是const的,并且您不应通过该指针修改字符串。在这种情况下,您仍然可以使用vector<char>,至少可以获得更轻松的内存管理优势。
还有一些与内存控制相关的注意事项:
C字符串是POD类型,所以它们可以在应用程序的只读数据段中分配。如果你在命名空间范围内声明并定义了std::string
常量,编译器会生成额外的代码,在main()
之前调用每个常量的std::string
构造函数。如果你的应用程序有许多常量字符串(例如如果你生成使用常量字符串的C++代码),那么在这种情况下使用C字符串可能更好。
一些std::string
的实现支持一种称为SSO("短字符串优化"或"小字符串优化")的特性,其中std::string
类包含存储长度不超过某个值的字符串的存储空间。这增加了std::string
的大小,但往往显著减少了自由存储区分配/释放的频率,从而提高了性能。如果你的std::string
实现不支持SSO,则在堆栈上构造一个空的std::string
仍将执行自由存储区分配。如果是这种情况,则对于使用字符串的性能关键代码,使用临时堆栈分配的C字符串可能会有帮助。当然,在这样做时要小心不要自己搬起石头砸自己的脚。
内存控制。最近我需要处理大约200-300 MB大小的字符串(实际上是来自数据库的二进制数据),在一个高度多线程的应用程序中。这种情况下,再复制一次字符串可能会使32位地址空间溢出。我必须确切地知道有多少个字符串副本存在。虽然我是STL的信奉者,但我使用了char *,因为它保证不会分配额外的内存或者进行额外的复制。我知道它需要多少空间。
除此之外,标准STL字符串处理还缺少了一些很棒的C函数用于字符串处理/解析。幸运的是,std::string有c_str()方法可以访问内部缓冲区。要使用printf(),你仍然需要使用char *(C++团队没有包含(s)printf类似的功能,这是一个多么疯狂的想法啊,这是C语言中最有用的函数之一。我希望boost::format很快会被包含在STL中。
教科书上使用老派的C字符串,因为许多基本函数仍然期望它们作为参数或返回它们。此外,它可以让人们更深入了解内存中字符串的底层结构。
遗留代码不知道 std::string。此外,在 C++11 之前,使用 std::ifstream 或 std::ofstream 打开文件只能将 const char* 作为文件名的输入。
如果C++代码“深入”(靠近内核,严重依赖于C库等),您可能希望显式使用C字符串以避免大量转换到和从std::string中。或者,如果您正在与其他语言域(Python,Ruby等)进行接口交互,出于同样的原因,您可能会这样做。否则,请使用std::string。
如果可以选择,通常没有理由选择原始的 C 字符串(char*
)而不是 C++ 字符串(std::string
)。然而,通常你没有选择的余地。例如,std::fstream
的构造函数采用 C 字符串,出于历史原因。此外,C 库(你猜对了!)使用 C 字符串。
在你自己的 C++ 代码中,最好使用 std::string
并通过使用 std::string
的 c_str()
函数 根据需要提取对象的 C 字符串。
void f(std::string s);
,你可以使用 f("C string");
调用该函数,因为 C 字符串可以隐式转换为 std::string
。 - wilhelmtell