当前位置:  开发笔记 > 编程语言 > 正文

C++:在评估顺序运算符时忽略括号

如何解决《C++:在评估顺序运算符时忽略括号》经验,为你挑选了1个好方法。

首先,我必须说这里提出的问题已经解决了,我想知道:

我误解了什么,

如果编译器有错误(我知道这很少见)(它是gcc 4.8.4).


我想计算一个二维向量的范数,其坐标仅在那一刻计算.比方说,我想计算|| (x0,y0) - (x1,y1)|| ,通过公式sqrt((x0-x1)**2 +(y0-y1)**2).只需要保存结果.

出于性能原因,方块是通过自乘法完成的,我希望变量和变量访问只能进行一次.我希望总计在运行时有效,并以某种方式优雅地编码.我想到了三种可能性:

重复两次x0 - x1y0 - y1,并希望compilator的优化步骤将检测到重复,

使用内联函数,

一起使用缓冲变量和顺序运算符.

我决定尝试最后一个选项.


现在考虑以下代码:

#include 
#include 

int main (void)
{
    float x0 (-1), x1 (2), y0 (13), y1 (9), result, tmp;

    result = std::sqrt ((tmp = x0 - x1, tmp * tmp) + (tmp = y0 - y1, tmp * tmp));
    printf ("%f\n", result);
}

我知道我必须得到5.000000,但我得到了5.656854,这是sqrt((y0-y1)**2 +((y0-y1)**2)).

我可以得到想要的结果:

#include 
#include 

int main (void)
{
    float x0 (-1), x1 (2), y0 (13), y1 (9), result, tmp, tmp2;

    result = std::sqrt ((tmp = x0 - x1, tmp * tmp) + (tmp2 = y0 - y1, tmp2 * tmp2));
    printf ("%f\n", result);
}

这就像首先评估顺序运算符的第一部分,忽略括号和第一个顺序运算符的返回值.似乎有点尴尬; 在这里我错过了C++的定义吗?

注意:在测试期间,打开或关闭优化设置不会改变任何内容.



1> Baum mit Aug..:

operator +可以交错地评估两侧.特别是,括号中的两个赋值中的每一个必须在乘法到其右边(在正确的代码中,即第一个变量不是)之前发生,但不需要在另一个赋值之前发生.此外,允许在一个赋值和匹配乘法之间发生另一个赋值.

因此,您的第一个变体会调用未定义的行为,因为它包含两个未经序列的修改tmp.所以每个结果都是合法的,包括崩溃或NaN.

一般来说,请记住"你的代码很聪明"并不是一种恭维.保持简单,如果你真的必须优化减法(你很可能不会):

auto dx = x0 - x1;
auto dy = y0 - y1;
auto result = std::sqrt(dx * dx + dy * dy);

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有