简体   繁体   English

C ++逻辑运算符返回值

[英]C++ logical operators return value

Here is some code I'm writing in C++. 这是我用C ++编写的一些代码。 There's a call to an addAVP() function 调用了addAVP()函数

dMessage.addAVP(AVP_DESTINATION_HOST, peer->getDestinationHost() || peer->getHost());

which has two versions: one overloaded in the second parameter to addAVP(int, char*) and another to addAVP(int, int) . 它有两个版本:一个在第二个参数中重载到addAVP(int, char*) ,另一个在addAVP(int, int) I find the C++ compiler I use calls the addAVP(int, int) version which is not what I wanted since getDestinationHost() and getHost() both return char* . 我发现我使用的C ++编译器称为addAVP(int, int)版本,这不是我想要的版本,因为getDestinationHost()getHost()都返回char*

Nonetheless the || 尽管如此|| operator is defined to return bool so I can see where my error is. 运算符定义为返回布尔值,因此我可以看到我的错误在哪里。 Bool somehow counts as an integer and this compiles cleanly and calls the second addAVP() . 布尔以某种方式计为整数,并且可以干净地编译并调用第二个addAVP()

Lately I'm using a lot of dynamically typed languages, ie lisp, where the above code is correct can be written without worries. 最近,我使用了许多动态类型化的语言,即lisp,上面的代码是正确的,可以编写而无需担心。 Clearly, clearly the above code in C++ is a big error, but still have some questions: 显然,上面的C ++代码显然是一个大错误,但仍然存在一些问题:

  1. Should I be using this kind of shortcut, ie using the ||-operator's return value, at all in C++. 我是否应该在C ++中使用这种快捷方式,即使用||运算符的返回值。 Is this compiler dependent? 这个编译器依赖吗?

  2. Imagine that I really, really had to write the nice a || b 想象一下,我真的不得不写一个漂亮a || b a || b syntax, could this be done cleanly in C++? a || b语法,可以在C ++中干净地完成吗? By writing an operator redefinition? 通过编写运算符重新定义? Without losing performance? 不损失性能?

As a followup to my original request, or my own answer to 2 :-) I was thinking along the lines of using a class to encapsulate the (evil?) rawpointer: 作为我最初的请求的后续行动,或者是我自己对2 :-)的回答,我一直在考虑使用类来封装(邪恶的)原始指针:

class char_ptr_w {
  const char* wrapped_;
public:
  char_ptr_w(const char* wrapped) : wrapped_(wrapped) {}
  char_ptr_w(char_ptr_w const& orig) {  wrapped_=orig.wrapped(); }
  ~char_ptr_w() {}
  inline const char* wrapped() const { return wrapped_; }
};

inline char_ptr_w operator||(char_ptr_w &lhs, char_ptr_w& rhs) {
  if (lhs.wrapped() != NULL)
    return char_ptr_w(lhs.wrapped());
  else
    return char_ptr_w(rhs.wrapped());
};

Then I could use: 然后我可以使用:

char_ptr_w a(getDestinationHost());
char_ptr_w b(getHost());

addAVP(AVP_DESTINATION_HOST, a || b);

In which this addAVP would be overloaded for char_ptr_w . 其中, addAVP将为char_ptr_w重载。 According to my tests, this generates at most the same assembly code as ternary a?b:c solution, particularly because of the NRVO optimization in the operator, which does not , in most compilers, call the copy-constructor (although you have to include it). 根据我的测试,这产生至多相同的汇编代码三元a?b:c的解决方案,特别是因为NRVO优化操作,这 ,在大多数编译器,调用拷贝构造函数(尽管你包括在内)。

Naturally, in this particular example I agree that the ternary solution is the best. 自然,在这个特定示例中,我同意三元解决方案是最好的。 I also agree that operator redefinition is something to be taken with care, and not always beneficial. 我也同意,重新定义操作员是要小心的事情,并不总是有益的。 But is there anything conceptually wrong, in a C++ sense, with the above solution? 但是,从C ++的角度来看,上述解决方案在概念上有什么问题吗?

It is legal in C++ to overload the logic operators, but only if one or both of the arguments are of a class type, and anyway it's a very bad idea. 重载逻辑运算符在C ++中是合法的,但前提是一个或两个参数均为类类型,无论如何这是一个非常糟糕的主意。 Overloaded logic operators do not short circuit , so this may cause apparently valid code elsewhere in your program to crash. 重载的逻辑运算符不会短路 ,因此这可能导致程序中其他地方的有效代码明显崩溃。

return p && p->q;  // this can't possibly dereference a null pointer... can it?

As you discovered, a bool is really an int. 如您所见,布尔确实是一个整数。 The compiler is picking the correct function for your footprint. 编译器正在为您的占用空间选择正确的功能。 If you want to keep similar syntax, you might try 如果您想保留相似的语法,可以尝试

char*gdh=0;
dMessage.addAVP(AVP\_DESTINATION\_HOST, 
                (gdh=peer->getDestinationHost()) ? gdh : peer->getHost());

I would strongly recommend against redefining the operator. 我强烈建议您不要重新定义运算符。 From a maintenance perspective, this is very likely to confuse later developers. 从维护的角度来看,这很可能会使以后的开发人员感到困惑。

Why are you using an "or" operator on two char pointers? 为什么在两个char指针上使用“或”运算符?

I am assuming that peer->getDestinationHost() or peer->getHost() can return a NULL, and you are trying to use the one that returns a valid string, right? 我假设peer-> getDestinationHost()或peer-> getHost()可以返回NULL,而您正在尝试使用返回有效字符串的对吧?

In that case you need to do this separately: 在这种情况下,您需要单独执行以下操作:


char *host = peer->getDestinationHost();
if(host == NULL)
  host = peer->getHost();
dMessage.addAVP(AVP\_DESTINATION\_HOST, host);

It makes no sense to pass a boolean to a function that expects a char *. 将布尔值传递给需要char *的函数没有任何意义。

In C++ || 在C ++中|| returns a bool, not one of its operands. 返回布尔值,而不是其操作数之一。 It is usually a bad idea to fight the language. 与语言作斗争通常是个坏主意。

1) Should I be using this kind of shortcut, ie using the ||-operator's return value, at all in C++. 1)我应该在C ++中使用这种快捷方式吗,即使用||运算符的返回值。 Is this compiler dependent? 这个编译器依赖吗?

It's not compiler dependent, but it doesn't do the same as what the || 它与编译器无关,但与||的功能不同 operator does in languages such as JavaScript or or in common lisp. 运算符使用JavaScript等语言or通用Lisp。 It coerces it first operand to a boolean values, and if that operand is true returns true. 它将第一个操作数强制为布尔值,如果该操作数为true,则返回true。 If the first operand is false, the second is evaluated and coerced to a boolean value, and this boolean value is returned. 如果第一个操作数为false,则对第二个操作数求值并强制为布尔值,然后返回此布尔值。

So what it is doing is the same as ( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) 所以它的作用与( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) ( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) . ( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) This behaviour is not compiler dependent. 此行为不依赖于编译器。

2) Imagine that I really, really had to write the nice a || 2)想象一下,我真的必须写一个漂亮的||。 b syntax, could this be done cleanly in C++? b语法,可以在C ++中干净地完成吗? By writing an operator redefinition? 通过编写运算符重新定义? Without losing performance? 不损失性能?

Since you are using pointers to chars, you can't overload the operator ( overloading requires one formal parameter of a class type, and you've got two pointers ). 由于您使用的是指向chars的指针,因此您不能重载运算符(重载需要一个类类型的形式参数,并且您有两个指针)。 The equivalent statement C++ would be to store the first value in a temporary variable and then use the ?: ternary operator, or you can write it inline with the cost of evaluating the first expression twice. 等效的C ++语句将第一个值存储在一个临时变量中,然后使用?:三元运算符,或者您可以内联地编写它,但要使用两次评估第一个表达式的代价。

You could instead do something like: 您可以改为执行以下操作:

dMessage.addAVP(AVP_DESTINATION_HOST, (peer->getDestinationHost())? peer->getDestinationHost() : peer->getHost()); dMessage.addAVP(AVP_DESTINATION_HOST,(peer-> getDestinationHost())?peer-> getDestinationHost():peer-> getHost());

This is not as neat as || 这不像||那样整洁。 but near to it. 但靠近它。

Well, you're right about what the problem is with your code: a || 好吧,您对代码的问题所在是正确的: b will return a bool, which is converted to int (0 for false, != 0 for true). b将返回一个布尔值,该布尔值将转换为int(对于false,为0,对于true为!= 0)。

As for your questions: 至于您的问题:

  1. I'm not sure whether the return value is actually defined in the standard or not, but I wouldn't use the return value of || 我不确定返回值是否实际上是在标准中定义的,但是我不会使用||的返回值。 in any context other than a bool (since it's just not going to be clear). 除了布尔值之外,其他任何情况下都没有(因为这还不清楚)。

  2. I would use the ? 我会用? operator instead. 运算符。 The syntax is: (Expression) ? 语法为:(表达式)? (execute if true) : (execute if false). (如果为true,则执行):(如果为false,则执行)。 So in your case, I'd write: (peer->getDestinationHost() =! NULL) ? 所以在您的情况下,我会写:(peer-> getDestinationHost()=!NULL)吗? peer->getDestinationHost() : peer->getHost(). peer-> getDestinationHost():peer-> getHost()。 Of course, this will call getDestinationHost() twice, which might not be desirable. 当然,这将两次调用getDestinationHost(),这可能不是所希望的。 If it's not, you're going to have to save the return value of getDestinationHost(), in which case I'd just forget about making it short and neat, and just use a plain old "if" outside of the function call. 如果不是这样,您将必须保存getDestinationHost()的返回值,在这种情况下,我会忘记使其简短而整洁,而在函数调用之外仅使用普通的旧“ if”即可。 That's the best way to keep it working, efficient, and most importantly, readable . 这是使它保持工作状态,高效且最重要的是可读性的最佳方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM