现在有什么好的理由在 C++ 中使用 C 字符串吗?我的教科书在某些时候在示例中使用了它们,我真的觉得使用 std::string 会更容易。
18 回答
我不得不使用它们的唯一原因是与使用 C 样式字符串的 3rd 方库交互时。出于性能原因,您可能还会在某些深奥的情况下使用 C 样式字符串,但通常情况下,由于内联和专门化等原因,在 C++ 字符串上使用方法可能更快。
在使用这类 API 时,您可以在许多情况下使用该c_str()
方法,但您应该知道返回的 char * 是 const,并且您不应该通过该指针修改字符串。在这种情况下,您仍然可以使用 vector<char> 代替,并且至少可以获得更轻松的内存管理的好处。
还有一些内存控制说明:
C 字符串是 POD 类型,因此它们可以分配在应用程序的只读数据段中。如果您在命名空间范围内声明和定义常量,编译器将生成在调用每个常量的构造函数std::string
之前运行的附加代码。如果您的应用程序有很多常量字符串(例如,如果您生成了使用常量字符串的 C++ 代码),在这种情况下 C 字符串可能更可取。main()
std::string
一些实现std::string
支持称为 SSO(“短字符串优化”或“小字符串优化”)的功能,其中std::string
该类包含存储到一定长度的字符串。这会增加std::string
但通常会显着降低自由存储分配/释放的频率,从而提高性能。如果您的实现std::string
不支持 SSO,则std::string
在堆栈上构造一个空仍将执行自由存储分配。如果是这种情况,使用临时堆栈分配的 C 字符串可能有助于使用字符串的性能关键代码。当然,当你这样做时,你必须小心不要射中自己的脚。
因为这就是它们来自众多 API/库的方式?
假设您的代码中有一些字符串常量,这是很常见的需求。最好将它们定义为 C 字符串而不是 C++ 对象——更轻量级、可移植等。现在,如果您要将这些字符串传递给各种函数,最好这些函数接受 C 字符串而不是需要C++ 字符串对象。
当然,如果字符串是可变的,那么使用 C++ 字符串对象要方便得多。
如果一个函数需要一个常量字符串,我仍然更喜欢使用 'const char*'(或 const wchar_t*),即使程序使用 std::string、CString、EString 或其他任何东西。
大型代码库中的字符串来源太多,无法确保调用者将字符串作为 std::string 并且 'const char*' 是最低公分母。
教科书以老式 C 字符串为特色,因为许多基本函数仍然期望它们作为参数,或返回它们。此外,它还可以深入了解内存中字符串的底层结构。
内存控制。我最近不得不在一个大规模多线程应用程序中处理大小约为 200-300 MB 的字符串(实际上是数据库中的 blob)。在这种情况下,字符串的多一份副本可能会破坏 32 位地址空间。我必须确切知道该字符串存在多少个副本。虽然我是一名 STL 传播者,但我当时使用了 char *,因为它保证了不会分配额外的内存甚至额外的副本。我确切地知道它需要多少空间。
除此之外,标准的 STL 字符串处理错过了一些用于字符串处理/解析的出色 C 函数。值得庆幸的是,std::string 具有 c_str() 方法,用于 const 访问内部缓冲区。要使用 printf() 你仍然必须使用 char * (C++ 团队的一个疯狂的想法是不包括(s)printf-like 功能,这是 C 中最有用的功能之一。我希望 boost::format 会很快就会被包含在 STL 中。
如果 C++ 代码很“深”(接近内核,严重依赖 C 库等),您可能希望显式使用 C 字符串以避免大量进出 std::string 的转换。当然,如果您正在与其他语言领域(Python、Ruby 等)交互,您可能会出于同样的原因这样做。否则,使用 std::string。
一些帖子提到了内存问题。这可能是避开 std::string 的一个很好的理由,但 char* 可能不是最好的替代品。它仍然是一种面向对象的语言。您自己的字符串类可能比 char* 更好。它甚至可能更有效 - 例如,您可以应用小字符串优化。
在我的例子中,我试图从一个 2GB 的文件中获取大约 1GB 的字符串,将它们填充到具有大约 60 个字段的记录中,然后对它们进行 7 次不同字段的排序。我的前辈代码使用 char* 花了 25 小时,我的代码在 1 小时内运行。
1)“字符串常量”是C字符串(const char *),将其转换为const std::string&是运行时过程,不一定简单或优化。2) fstream 库使用 c 风格的字符串来传递文件名。
我的经验法则是传递 const std::string& 如果我无论如何都要将数据用作 std::string (例如,当我将它们存储在向量中时),而在其他情况下传递 const char * 。
在花费了太多时间调试初始化规则和几个平台上每个可能的字符串实现之后,我们需要静态字符串为 const char*。
在花费了太多时间调试错误的 char* 代码和内存泄漏之后,我建议所有非静态字符串都是某种类型的字符串对象......直到分析表明你可以而且应该做得更好;-)
不知道 std::string 的遗留代码。此外,在 C++11 之前,使用 std::ifstream 或 std::ofstream 打开文件只能使用 const char* 作为文件名的输入。
给定选择,通常没有理由选择原始 C 字符串 ( char*
) 而不是 C++ 字符串 ( std::string
)。但是,您通常没有选择的余地。例如std::fstream
,由于历史原因, 的构造函数采用 C 字符串。此外,C 库(您猜对了!)使用 C 字符串。
在您自己的 C++ 代码中,最好std::string
使用c_str()
.std::string
这取决于您使用的库。例如,在使用MFC时,在使用 Windows API 的各个部分时使用 CString 通常更容易。在 Win32 应用程序中,它似乎也比 std::string 执行得更好。
但是,std::string 是 C++ 标准的一部分,因此如果您想要更好的可移植性,请使用 std::string。
对于大多数嵌入式平台等应用程序,在这些应用程序中,您没有奢侈的堆来存储被操作的字符串,并且需要确定性地预分配字符串缓冲区。
c 字符串不承担成为类的开销。
c 字符串通常可以产生更快的代码,因为它们更接近机器级别
这并不是说,你不能用它们编写糟糕的代码。它们可能被滥用,就像其他所有构造一样。
由于历史原因,有大量的库调用需要它们。
学习使用 c 字符串和 stl 字符串,并在有意义的时候使用它们。
STL 字符串当然更容易使用,我看不出有任何理由不使用它们。
如果您需要与仅将 C 样式字符串作为参数的库进行交互,您始终可以调用 string 类的 c_str() 方法。
这样做的通常原因是您喜欢在字符串处理中写入缓冲区溢出。计数字符串优于终止字符串,很难理解 C 设计者为什么使用终止字符串。那时这是一个糟糕的决定。现在这是一个糟糕的决定。