C++运算符顺序评估

3

我有代码,但是它给我编译错误。 我期望从左到右进行运算符优先级的评估。'name += ":"' 的结果是字符串,但看起来它先评估了":" + "O"。我没有找到任何清晰的解释。

#include <string>

int main()
{
  std::string name("HELL");
  name += ":" + "O";
  std::cout << "Hello, " << name << "!\n";
}

1
请查看运算符优先级 - Scheff's Cat
3个回答

6
表达式name += ":" + "O"被分组为name += (":" + "O")。但是,由于“:”“0”const char [2]类型,在该表达式中会衰减为const char*指针;而指针不能相加!从C++14开始,您可以使用用户定义的字面量 ""s+置于“字符串模式”中:
name += ""s + ":" + "O"

分组规则已经硬编码到语言的 语法 中,尽管按照 运算符优先级和结合性 来思考更为方便。


为什么不直接使用 name += ":"s + "O";?有什么区别吗? - Daniel Langr
2
@DanielsaysreinstateMonica:如果真的存在这个问题,我会和我的编译器供应商进行严肃交流。但实际上,你只需要使用:0就可以了。 - Bathsheba
在 C++14 之前:name += std::string("") + ":" + "O" 可能是这样的吧? - YSC
@YSC,确实,尽管它不是很可爱。而Java的人们则用C++14的方式来做。虽然相比之下这种语言很丑陋:不允许操作符重载,但又以某种方式允许java.lang.String进行操作符重载。 - Bathsheba
或者你可以直接移除 +name += ":" "0";。预处理器会将相邻的字符串字面量连接起来,这样就消除了临时的 std::string 对象。 - Pete Becker

3
根据运算符优先级operator+的优先级高于operator+=,因此name += ":" + "O";被解释为name += (":" + "O");,而":" + "O"是无效的,您不能添加两个指针(":""O"将会衰减为类型为const char*的指针)。
您可以添加()来指定优先级,例如(name += ":") + "O";,它可以编译,但请注意部分+ "O"在这里变得没有意义。或者,如@Scheff所建议,您可能想要(name += ":") += "O";,这取决于您的需求。

1
当你开始考虑使用括号来打破优先级时,也许可以尝试 (name += ":") += "O"; - Scheff's Cat
1
@Scheff 已添加到答案中;它可能符合 OP 的意图,但我不确定。 :) - songyuanyao
1
@Scheff 哇,这个 += 的链接看起来对我来说很丑陋。我不太清楚为什么,因为我很高兴地链接 std::cout << ... << ...,但是用 += 来做这件事感觉就错了。 :) - Frodyne
1
@Frodyne 是因为 () 吗?operator+= 的结合性是从右到左的,如果没有 ()":" += "O" 将首先被计算,但这是无效的。 - songyuanyao
@Frodyne 如果有更多的参数就会变得很丑陋(越来越接近Lisp程序)。在这种情况下,最好重复左侧而不是使用更多参数。虽然我认为这对编译器没有影响,但对于人眼和心情肯定更好。 - Scheff's Cat

0

这个带有复合赋值的表达式语句

name += ":" + "O";

实际上等同于

name = name + ( ":" + "O" );

在这个子表达式中

( ":" + "O" )

字符串字面量被转换为它们第一个元素的指针。然而,指针并没有定义二进制运算符 +。因此编译器会发出错误。

您可以将原始语句拆分为两个语句,例如

name += ":";

并且

name += "O";

在这种情况下,将使用为 std::basic_string 类定义的运算符 +,其接受类型为 const char * 的参数。

(挑剔: "等价于' name = name + ...' " - 带有表达式 'name' 仅被计算一次的警告)。 - Max Langhof
@MaxLanghof 在这个问题的背景下,这完全不重要。 - Vlad from Moscow
@VladfromMoscow:但是你提交了一个冗长的答案,所以我也认为你应该提到它。(你注意到我在我的回答中完全避免了这个问题吗?!) - Bathsheba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接