如何使C++编译器遵循与C#在该赋值语句中相同的优先级、关联性和求值顺序
How to make the C++ compiler to follow the same precedence, associativity and order of evaluation that C# has in the this assignment statement?
考虑以下代码:
int x = 1;
int y = 2;
y = x + (x = y);
当这在C#中运行时,变量最终被分配了以下值:
x=2
y=3
另一方面,当同样的程序在C++中运行时,变量的结尾是这样的:
x=2
y=4
显然,C++编译器使用的优先级、关联性和评估顺序规则与C#不同(如Eric Lippert的文章中所解释的(。
所以,问题是:
是否可以重写赋值语句以强制C++进行与C#相同的求值
唯一的限制是将其作为一个衬垫。我知道这可以通过将作业分成两行来重写,但目标是将其保持在一行中。
是的,这确实是可能的。
x = (y+=x) - x;
这么简单。
是否可以重写赋值语句以强制C++像C#一样求值?
是。为了澄清,C#中的规则是,大多数情况下,表达式的左侧在右侧之前完全求值。所以C#保证+
左边的x
的评估发生在右边的x = y
的副作用之前。C++不作此保证;编译器可能对这个表达式的含义意见不一。
(挑战:我说"大多数"是有原因的。举一个C#中的一个简单表达式的例子,左边的副作用是在右边的副作用之后执行的。(
我知道这可以通过将分配拆分为两行来重写
右。你希望有一个有两个副作用的语句:用x的原始值增加y,并将y的原始值赋给x。所以你可以把它写成
int t = y;
y = y + x;
x = t;
但是:
目标是将其保持在一行中。
我认为"line"的意思是"statement"。好的只需使用逗号运算符。
int t = ((t = y), (y = y + x), (x = t));
很简单。我不知道你为什么要。我想这是一个谜题,旨在引出关于你是否知道逗号运算符的信号。
额外学分:那份报表中需要多少括号?
超级奖励:如果我们不想使用逗号运算符怎么办?我们可以使用其他运算符作为排序运算符。
int t = ((t = y) & 0) || ((y = y + x) & 0) || (x = t);
我们执行||
的左边,结果是false,所以我们执行右边,以此类推
类似地,((expr1) & 0) ? 0 : (expr2)
保证expr1
在expr2
之前运行。
基本上,这里需要的是保证许多子表达式按特定顺序发生。查找"序列点",看看C和C++中的哪些运算符产生序列点;您可以使用它们对表达式进行排序,因此得名。
您可以编写:
int x = 1;
int y = 2;
y = std::exchange(x,y) + y;
但高度不受欢迎。你甚至不得不停止浏览,想想这个简单的操作。
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 使用2个键的cpp-stl::优先级队列排序不正确
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 打印优先级队列
- 带自定义比较器的最小优先级队列
- 优先级队列自定义比较器
- C++ 优先性和关联性
- 排序数组优先级队列
- 更改运行时优先级队列的排序功能
- 优先级队列构造函数的工作
- 实现优先级队列
- 优先级队列功能比较
- C++ 带有函数指针的运算符优先级
- 将更高的优先级设置为 boost::asio 线程处理进程
- 如何使C++编译器遵循与C#在该赋值语句中相同的优先级、关联性和求值顺序
- 是否违反 C/C++ 运算符优先级和关联性规则?
- C/C++ 中的运算符优先级和关联性
- C++ 中的运算符优先级和运算符关联性规则
- 编译器如何根据优先级和关联性解释此表达式