c++中的逻辑AND+赋值,安全

Logical AND + assignment in c++, safe?

本文关键字:赋值 安全 AND+ c++      更新时间:2023-10-16

我刚刚(实际上是从javascript)学到了这个很棒的模式,我想把它应用到我的c++代码中。

为了解释这种模式,假设我将一个字符串表示为以下内容的链表:

struct link_char;
struct link_char
{
   link_char * next;
   char code;
};

请注意,任何link_char字符串的最后一个字符的代码始终为==0。这个属性意味着我可以在使用&短路以防止NULL指针访问。

bool equals_hello( const link_char * first_char )
{
    const link_char * c = first_char;
    return       c->code=='h' 
    && (c=c->next)->code=='e' 
    && (c=c->next)->code=='l' 
    && (c=c->next)->code=='l' // if string == "hel", we short-circuit here
    && (c=c->next)->code=='o';
}

我的问题是关于安全性,而不是可读性。我知道只要&没有过载。但是,分配操作是按照正确的顺序进行,还是定义了实现?

上面的例子明确说明了读/写可能发生的地方,但我也希望在可能有副作用的情况下使用这种模式。例如:

// think of these as a bunch of HRESULT type functions 
//   a return value of 0 means SUCCESS
//   a return value of non-zero yields an Error Message
int err;
( !(err=initialize()) && !(err=create_window()) && !(err=run_app() )
    || handle_error(err);

这些类型的操作是否可以跨平台运行?我读过"如果你在一个表达式中读了两次变量,同时也写了它,结果是未定义的"。但凭直觉,我觉得短路保证了秩序,不是吗?

是。

内置逻辑AND(&&)、逻辑OR(||)和逗号运算符(,

还要注意,函数参数之间的逗号不是逗号运算符,因此没有指定函数参数的求值顺序,甚至比这更糟:例如,在f(g(h()),i())中,调用序列可能是h,i,g,f

此外,关于评估顺序的保证仅适用于内置运算符;如果重新定义它们,那么它们基本上就变成了函数调用,在函数调用中,参数的求值顺序得不到保证,也不执行短路。

其他二进制运算符不能保证求值的顺序,例如,一个常见的错误是认为:
std::cout << foo() << bar();

对CCD_ 6的调用保证在对bar()的调用之前发生。。。这不是真的。

(C++17修复了这个问题,但仅在少数非常特殊的情况下,包括左移运算符,因为它用于流)

当然,三元:?运算符的求值顺序也是有保证的,其中在第一次求值条件后,将只求值另外两个表达式中的一个。

另一个保证求值顺序的地方(有时会让新手感到惊讶)是构造函数的成员初始化列表,但在这种情况下,顺序是而不是表达式中的顺序,而是类中成员声明的顺序。。。。例如:

struct Foo
{
   int x, y;
   Foo() : y(compute_y()), x(compute_x()) {}
};

在这种情况下,保证调用compute_x()将在调用compute_y()之前完成,因为在成员声明中xy之前。

这些操作会起作用吗打算跨平台?我读过如果你在一个你也写它的表达式,结果是未定义的"。但是凭直觉我觉得短路保证了秩序,不是吗?

内置的&&运算符保证了短路评估,这意味着它引入了一个序列点:C++98§5.14/2"第一个表达式的所有副作用,除了临时性(12.2)的破坏,都发生在第二个表达式评估之前"。

所以使用C++没有问题。

不过,在我看来,你建议的用法很不好,因为它晦涩难懂。简单地说,不要使用你必须询问的语言功能,因为其他人很可能也不清楚。此外,在代码中重新注释,请注意,当设置位31时,Windows HRESULT表示失败,这与零/非零非常不同。

干杯&hth。,