string literals 和 standard library strings

2022-04-30 14:13:59 +08:00
 vcfghtyjc

看《 C++ Primer 》里提到

For historical reasons, and for compatibility with C, string literals are not standard library strings.

简单翻译一下就是“由于历史原因,同时为了兼容 C 语言,string literals 不是标准库中的 string

好像因为这个原因 string s = "hello" + "world"; 会报错,因为 string literals 不能相加。

感觉这个设定好反直觉,允许它们相加就这么难吗?如果之前不允许,那么应该没人在代码里这么使用,那么增加相加这个功能应该不会导致不兼容过去的代码吧?

1498 次点击
所在节点    C++
9 条回复
justou
2022-04-30 15:41:30 +08:00
"hello"的类型是 const char[6], 作为数组相加吗? 如果可以的话,
const char[2] + const char[3]怎么加?
const int[4] + const int[4]怎么加?

char, short, int, long 等都是 integral, 除了数值能表示的范围, 没啥特殊

这样可以
using std::operator""s;
auto s = "hello"s + "world";
ColorfulBoar
2022-04-30 23:32:27 +08:00
string concatenation 构成一个 nonabelian semigroup ,用加法完全不符合直觉,还不如写成"hello" "world"这样当成是省略了乘号的乘法。
另外要不要考虑一下放过可怜的 operator ,多跟 format 玩玩?
vcfghtyjc
2022-04-30 23:42:26 +08:00
@ColorfulBoar 不懂 nonabelian semigroup ,如果不知道这个概念,使用加号表示链接应该挺符合直觉的吧。不然其他语言也不会说允许用➕ 链接字符串。
ColorfulBoar
2022-05-01 00:23:42 +08:00
@vcfghtyjc 一般加法暗示运算是可交换的,乘法不一定保证交换,矩阵乘法总还是见过的吧?另外把 s 和 t 拼接起来的串不就是 st 么,反而 s+t 看着怪怪的,而且任何一个稍微正经一点讲字符串的地方(定义了什么是 alphabet 什么是 string 的)应该也都是用前面的记号表示 concatenaion 。再换个思路,考虑两个字符串的集合 A ,B ,那一般情况下 A 里面的串 a 和 B 里面的串 b 拼起来的所有可能情况也更接近 A 和 B 的笛卡尔积(模掉一点重复的情况)而不是不交并(那个是集合的加法)(不理解 universal property 可以直接数集合里面包含多少个元素也可以理解为什么前者叫乘法后者叫加法)。所以不管怎么想都是乘法更合适,至于为什么这么多语言选择用加号……懒得查始作俑者是谁了,剩下的怕不是互相抄了抄压根就没过脑子,不然总得说出来一个把 operator*保留下来的合理用处吧?
secondwtq
2022-05-01 08:07:39 +08:00
编程是一个逻辑的事情,和“直觉”有什么关系呢?
yulon
2022-05-01 09:58:20 +08:00
你可以自己重载 +,但是别人的老代码不接受你的污染罢了,而且 + 存在多个输入也并不高效,除非编译器开洞,但是开洞就变成另一个新语言了,所以没人用 +,自然也没人关心改动 +。
vcfghtyjc
2022-05-01 11:12:21 +08:00
@ColorfulBoar 问题不在于加号是否能表达正确含义。事实上 `String s = s0 + "1"` 是可以运行的,也就是在 C++ 中➕ 也是可以表示链接字符串的。问题在于这个符号对 String literal 和 String 表现出了不一致的行为,这点感觉只是增加了学习门槛,没什么益处。
vcfghtyjc
2022-05-01 11:13:36 +08:00
@secondwtq 编程语言是工具,符合逻辑是让工具更顺手,降低学习门槛,不然也不会从 01 的机器语言编程如今的高级语言。
ColorfulBoar
2022-05-01 13:09:12 +08:00
@vcfghtyjc C++本来就不是一次性精心设计出来的语言,再把那些兼容 C 的东西放进来之后就更混乱邪恶了。这种时候做一件事情会有多种方式,其中的一些虽然凑合着能用编译器不会干死你但精神上不太正确 /属于历史残留问题(比如某些 best practices 里面三番五次提醒过不要用的),所以 C++里某种写法语义正确完全不代表应该接着用它们,强求一致性更是没意义与不可能的。如果想写一个优美点的语言,你就不能把所有语法同等对待,必须自己裁剪一部分出来顺带着对一些旧东西进行新的解读,而做这些事情的依据不是 C++内部能确定的,得由来自外部的知识确定,这大概是我想强调哪个(至少精神上)更「正确」的原因。
至于学习门槛……现在 C++的学习 /教学上问题当然非常大,我觉得最麻的还是初学者刚上来基本上是在大量过时 /误导性的材料里面游泳,而不是符不符合直觉这种事情(毕竟一般人的直觉很多是错的,如果一个人直觉比较准的话那它大概自己也知道咋学了不太容易被各种坑人的东西整蛊到)。

关于你具体的问题……我觉得不应该把 string literal 看成是某种老式的 std::string ,它(作为指向一段 char const 的 handle )更像是个扭曲的 std::string_view ,这下子二者都不支持 operator+了( view 对“运算”不封闭:把两个 view 拼在一起并不能得到一个新的 view ),是不是顺眼一点了?
(当然这是种重新解读后的结果,毕竟别说刚整出(C) string literal 的时候还没有 string_view 了,好像你看的这书因为有点老里面也没有它……)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/850206

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX