为啥 C++ 中有这么多字符串类型?

Posted

技术标签:

【中文标题】为啥 C++ 中有这么多字符串类型?【英文标题】:Why are so many string types in C++?为什么 C++ 中有这么多字符串类型? 【发布时间】:2017-08-11 11:15:06 【问题描述】:

我喜欢 C,我有一本名为 Full and Full C and 2 C++ 的 C 书,我发现这些语言非常棒,因为它们具有令人难以置信的功能和性能,但由于这些不同的类型,我不得不结束我的许多项目。

我说有std::stringLPCSTRSystem::StringTCHAR []char s [] = "ss"char * s

这主要在GUI应用程序中引起巨大的头痛,WinAPI存在LPCSTR与char或std::string不兼容的问题,现在在CLR应用程序中如果它有System::String,那么转换为很头痛std::Stringchar * s 甚至 char s []

为什么 C/C++ 的字符串类型不像 Java 中的 String 那样是唯一的?

【问题讨论】:

C 只有(以空结尾的)char 数组和字符串文字,没有 string 类型。而 C++ 提供了一些字符串类(最重要的是 std::string)作为其标准库的一部分,LPCSTRSystem::String 不是语言标准的一部分 Java 中唯一的字符串类型是 C++ 中的 std::string 和 C 中以 '\0' 结尾的 char[]。除此之外的其他类型是 typedef、结构或自己的类,这不是C 或 C++ 的错误。 实际上,LPCSTR 只是一个char *,正如在 microsoft winapi 文档中也指出的那样。另见:***.com/questions/1200188/… 使用std::string - that 是可接受的 C++ 字符串类型。尽管可以使用遗留的 C 字符串,但它们使用起来很恐怖。其他都是非标准的。 "我希望 C/C++ 的 String 类型与 Java 中的 String 是唯一的。" 那么你为什么要比较 3 个 不同的语言,并问为什么它们有不同的字符串类型,而 Java 只是一种语言? C 有 char*/char[](以空字符结尾的字符数组)。 C++ 有std::string,C++/CLI(又一种语言!)有System::String。 WinApi 中的LPCTSTR 只是TCHAR const * 的typedef,其中TCHAR 是charwchar_t,取决于是否定义了UNICODE。您可以看到为什么它可能与std::string 不兼容。 【参考方案1】:

没有“c++ 中有多种类型的字符串”。典型地有一个模板std::basic_string,它基本上是一个专门用于不同字符类型的字符串的容器。

std::stringstd::basic_string<char> 上的便捷类型定义。对于不同的底层字符类型,还有更多这样的 typedef。

AFAIK,标准 c 也只有一个官方认可的字符串标准。它是 ANSI 字符串,即以空结尾的 char 数组。

您提到的所有其他内容要么与此等效(例如,LPCSTR 是指向常量字符串的长指针,即const char*),要么是库提供者编写的一些非标准扩展。

您的问题就像问为什么有这么多 GUI 库。因为没有标准方法可以做到这一点,或者在某些方面缺乏标准方法,提供和支持自己的等效类型是一个设计决定。

底线是,在库级别或语言级别,这是不同权衡之间的设计决策。简单,性能,字符支持等等等等。总的来说,storing text is hard。

【讨论】:

C 中没有“ansi 字符串”之类的东西。C 中有许多不同种类的字符串,包括宽字符串、char16_t 字符串和 char32_t 字符串。 您能否指出 C 标准中的一个可以定义任何字符串的字符串,以便我补充我的答案?我尝试在a draft 中搜索char32_t,但一无所获。我确信以空字符结尾的字符串是标准化的,但我可能错了。我不是真正的 C 专家。 @luk32: C 2011 Online Draft,第 7.1.1 节。 @luk32 版本错误。 C11 最终草案,又名n1570【参考方案2】:

好吧,首先我们必须回答这个问题:什么是字符串?

C 标准将其定义为以第一个空字符终止并包括在内的连续字符序列。1 它还提到了使用wchar_tchar16_tchar32_t 而不是char 的品种。 它还提供了许多用于字符串操作的函数,以及用于表示方便的字符串文字。

所以,一个字符序列可以是一个字符串,char[] 可能包含一个字符串,而char* 可能指向一个。LPCSTRconst char* 的 Windows 类型定义,并添加了它应该指向一个字符串或 NULL 的语义。TCHAR 是用于将 Windows 代码从 char 转换为 wchar_t 的众多预处理器定义之一。根据TCHAR 是什么,TCHAR[] 可能能够容纳字符串或宽字符串。


C++ 有点混乱,因为它添加了一种用于处理字符串的数据类型。为了减少歧义,string只用于抽象概念,你必须依靠上下文来消除歧义或更明确。

所以 C string 对应于 C++ null-terminated-byte-string,或 NTBS2 是的,C++ 也知道它们的多样性。 而 C++ 合并了 C 函数并添加了更多函数。 此外,C++ 有std::basic_string<> 用于存储各种计数字符串,以及一些方便的typedef,如std::string


现在我们开始使用第三种语言,即 C++/CLI。 它结合了我上面从 C++ 中谈到的所有内容,并将 CLI 类型 System::String 添加到组合中。System::String 是一个不可变的 UTF-16 计数字符串。


现在回答为什么 C++ 没有将一个具体类型定义为字符串的问题可以回答:

为了互操作性、历史性、效率和便利性,C++ 中有不同类型的字符串。始终为工作使用正确的工具。 Java 和 .Net 对 byte-arrays、char-arrays、string-builders 等做同样的事情。


参考1:C11最终草案,字符串定义:

7。图书馆

7.1 简介

7.1.1 术语定义

1 string 是由第一个空字符终止并包括第一个空字符的连续字符序列。有时使用术语多字节字符串来强调对字符串中包含的多字节字符进行特殊处理或避免与宽字符串混淆。 指向字符串的指针 是指向其初始(最低地址)字符的指针。 字符串的长度是空字符之前的字节数,字符串的值是包含的字符的值的顺序,按顺序排列。

参考 2:C++1z 草案 n4659 NTBS:

20.4.2.1.5.1 字节字符串[byte.strings]

1 空终止字节字符串NTBS是一个字符序列,其具有已定义内容的最高地址元素的值为零(终止空字符);序列中没有其他元素的值为零。163 2 NTBSlength 是终止空字符之前的元素数。 empty ntbs 的长度为零。 3 NTBSvalue 是元素的值序列,直到并包括终止空字符。 4 static NTBS 是具有静态存储持续时间的 NTBS。164

【讨论】:

【参考方案3】:

每个字符串类型都有自己的目标,std::string 用于标准库,这是最常见的。

正如您所说,C++ 具有强大的功能和性能,并且这些字符串具有更大的灵活性。 Char[]char* 可以用于更通用的字符串用法。

【讨论】:

以上是关于为啥 C++ 中有这么多字符串类型?的主要内容,如果未能解决你的问题,请参考以下文章

为啥有这么多 mime 类型?

Visual C++中有多少种类型的字符串

CloudKit - 使用一种字段类型获取 5 条记录...需要 3-4 秒。为啥这么慢?

两段c++代码功能一样为什么运行时间差这么多???

为啥 char** 不能成为 C++ 中以下函数的返回类型?

Java中double类型的变量,计算结果的小数点后为啥会有这么多0?