在c ++中进行逻辑AND +赋值,安全吗?

时间:2011-07-01 05:56:55

标签: c++ c cross-platform variable-assignment logical-operators

我刚刚学会了这个伟大的模式(实际上来自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';
}

我的问题是关于安全性,而不是可读性。 我知道只要&& amp;&&没有超载。但是,赋值操作是否会以正确的顺序发生,还是实现定义?

以上示例明确说明了读/写可能发生的位置,但我也想在可能存在副作用的情况下使用此模式。例如:

// 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);

这些类型的操作是否可以按预期的跨平台工作?我已经读过“如果你在一个表达式中读取变量两次,你也写了它,结果是未定义的”。但直觉上我觉得短路保证了订单,不是吗?

2 个答案:

答案 0 :(得分:15)

内置逻辑AND(&&),逻辑OR(||)和逗号运算符(,)是 only 个案,其中for一个二元运算符C ++保证评估将计算左表达式然后(如果不是短路)右表达式(逗号运算符当然总是计算两个操作数,先左,然后右)。

另请注意,函数参数之间的逗号不是逗号运算符,因此未指定函数参数的计算顺序,甚至更糟:例如在f(g(h()),i())中,调用序列可能将是h,i,g,f

评估订单的保证仅适用于内置运营商;如果你重新定义它们,那么它们基本上成为函数调用,其中不保证参数的评估顺序以及不执行短路的情况。

其他二元运算符不保证评估的顺序,例如,一个常见的错误是认为:

std::cout << foo() << bar();

foo()的来电保证会在致电bar()之前发生......这是为真。

当然,三元 :?运算符的评估顺序也是有保证的,其中在首次评估条件后,只评估其他两个表达式中的一个。

保证评估顺序的另一个地方(对于新手来说有时令人惊讶)是构造函数的成员初始化列表,但在这种情况下,顺序是表达式中的那个,但是类中成员声明的顺序....例如:

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

在这种情况下保证,呼叫compute_x()将在呼叫compute_y()之前完成,因为x在成员y之前声明。

答案 1 :(得分:3)

  

这些操作是否有效   打算跨平台?我读了   “如果你读了两次变量   一个表达式,你也写它,   结果未定义“。但是   直觉上我觉得像   短路保证了订单,   不是吗?

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

所以没有问题。 C ++。

仍然你的建议用法在我看来非常不好,因为它很模糊。只是不要使用你必须要问的语言功能,因为其他人很可能同样不清楚它们。此外,在代码中重新注释,请注意,当设置第31位时,Windows HRESULT指示失败,这与零/非零非常不同。

干杯&amp;第h。,