在这种情况下使用多个条件运算符是个好主意吗?
我刚刚在关于条件运算符的 Wikipedia 文章中看到了这段代码:
Vehicle new_vehicle = arg == 'B' ? bus :
arg == 'A' ? airplane :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? horse :
feet;
我稍微改变了代码,但想法是一样的。您认为条件运算符的这种使用可以接受吗?它比 if
-else
结构简洁得多,并且使用 switch 肯定会带来一系列全新的错误机会(有人会失败吗?)。另外,if
-else
s 和 switch
不能用作 R 值,因此您必须先创建变量,对其进行初始化,然后根据需要进行分配。
我真的很喜欢这个,但我想知道其他人的想法。
但格式化是必不可少的。
编辑:我还是喜欢这个。但我理解那些说“switch 语句就是为此而创建的”的人。好吧,也许是这样。但是,如果条件是返回 bool 的函数调用怎么办?或者还有一百万个你无法打开的其他东西。
你们换恋人真的想让我相信一个巨大的 if
-else
链更好吗?是的,不知道如何使用条件运算符的程序员不会理解这一点。他们应该学习如何使用它。这并不神秘。
I just saw this block of code on the Wikipedia article on conditional operators:
Vehicle new_vehicle = arg == 'B' ? bus :
arg == 'A' ? airplane :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? horse :
feet;
I've changed the code a little, but the idea is the same. Would you find this use of the conditional operator acceptable? It's much more concise than the if
-else
construct, and using a switch would definitely open up a whole new set of opportunities for bugs (fall-throughs anyone?). Also, if
-else
s and switch
can't be used as R-values, so you'd have to create the variable first, initialize it and then assign as necessary.
I for one really like this, but I'm wondering what others think.
But the formatting is essential.
EDIT: I still like this. But I understand those who say "the switch
statement was made for this". OK, maybe so. But what if the conditions are function calls that return bool
? Or a million other things you can't switch on.
Are you switch lovers really trying to convince me that a huge if
-else
chain is better? Yes, programmers who don't know how to use the conditional operator will not understand this. They should learn how to use it. It's not arcane.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
我已经多次使用过这种类型的结构。只要它的格式很好(即不是全部在一行上,使其不可读),我不认为它有问题。
I have used this type of construction many times. As long as it's formatted nicely (i.e. not all on one line, making it unreadable), I don't see a problem with it.
我会使用开关,因为这就是它的设计目的。是的,存在出现错误的风险,但是这种嵌套条件块被其他程序员误解的风险要高得多。
I would use a switch, because this is the kind of thing it was designed for. Yes, there is a risk of fall-through bugs, but this nested-conditional block has a much higher risk of being misunderstood by other programmers.
这是条件运算符使用的一个很好的例子。我在 C++、Java 和 Perl 中一直以这种方式使用它。
This is a great example of conditional operator use. I use it in this manner all the time in C++, Java, and Perl.
它不仅没有任何问题,而且以最简洁、最清晰的方式传达了操作的意图。
用 if else 或 switch 结构替换需要
在每个实例中重复该片段,这要求读者阅读它的每个重复实例以确保它在每个实例中实际上都是相同的。
Not only is there nothing wrong with it, it communicates the intent of the operation in the most concise and clear way possible.
Replacing with if else, or switch construction requires that the snippet
be repeated in every instance, which requires that the reader read every repeating instance of it to ensure that it is in fact the same in every instance..
我喜欢它。它类似于 if-else-if 梯子,只是更简洁。
I like it. It is similar to an if-else-if ladder, only more concise.
字符常量周围有很多空格,这使得阅读起来有点困难。我会将比较括起来:(并且可能会移动行中的最后一个值。)
现在看起来很棒。
There's a lot of whitespace around the character constants that makes it a bit hard to read. I'd parenthesize the comparisons: (and maybe move the last value in line.)
Now it looks great.
条件运算符版本干净、简单,任何了解 C 或 C++ 的人都会立即明白发生了什么。它的另一个优点是它立即返回一个值,这意味着它可以放入初始化中(就像这个例子一样)。
switch 语句会更加笨拙。它需要声明变量然后初始化,如果可以避免的话,这通常是一个坏主意。这将需要更多的打字,并且会有更多的地方让错误潜入。它不会那么清楚,因为有必要查看每个案例以查看它是否说了类似
new_vehicle = foo; 的内容。中断;
。如果您只想在这里进行查找,那么有条件版本就很好,因为它可以立即显示正在发生的情况。如果它会发生多次,请考虑将其放入一个函数中,以便在发生任何变化时只有一个位置可以更新(例如,“R”代表马车或“L”代表直升机)。
The conditional operator version is clean, simple, and it's immediately obvious to anybody who knows C or C++ what is happening. Its other virtue is that it returns a value immediately, which means it can be put in the initialization (like this example is).
A switch statement would be more clumsy. It would require that the variable be declared and then initialized, usually a bad idea if it can be avoided. It would take more typing, and would have more places for bugs to creep in. It wouldn't be as clear, since it would be necessary to look at each case to see that it said something like
new_vehicle = foo; break;
.If you're going to do this look up here only, then having the conditional version right there is good, as it immediately shows what's happening. If it's going to occur more than once, consider putting it in a function, so that there's only one place to update if anything changes (such as, say, 'R' for carriage or 'L' for helicopter).
纯粹是一种风格选择。对于像您在这里展示的小数据集,只要您的编程团队没有被这样的事情困扰,那么在我的书中就可以了。
Purely a stylistic choice. For small data sets like you present here, then as long as your programming team isn't thrown by such a thing, then its fine in my book.
切换更清晰,而且可能更有效。如果我在代码审查中看到这样的代码,我会担心。另外,这是“条件运算符”——它是三元运算符的一个实例(尽管目前是 C 和 C++ 中唯一的一个)。
A switch is both clearer and possibly much more efficient. If I saw code like this at a code review, I'd be worried. Also, this is "the conditional operator" - it is an instance (albeit currently the only one in C and C++) of a ternary operator.
我更喜欢这个。嵌套条件很聪明,但我认为这几乎同样简洁,而且不太可能让未来的读者感到困惑。抱歉,如果语法不正确,我现在没有做太多 C 工作。
编辑:修复了注释中指出的返回类型遗漏。谢谢!
编辑:顺便说一句,我对你的版本并不感到害怕。当我看到它时,我并没有惊呼“WTF”或“OMG”。我只是更喜欢我的:)
I like this better. The nested conditional is clever, but I think this is almost as concise and less likely to confuse a future reader. Sorry if the syntax is off, I'm not doing much C nowadays.
EDIT: Fixed return type omission noted in comments. thx!
EDIT: I'm not horrified at your version by the way. I did not exclaim WTF or OMG when i saw it. I just prefer mine a little more :)
我不是特别关心它。
它并没有真正购买任何东西,或者使任何东西变得更清晰,而且这是运算符的非常非标准的用法。
看起来主要的优点是它有点聪明。我会避免聪明,除非有一个很好的(外部)理由要聪明。
I don't particularly care for it.
It doesn't really buy anything, or make anything more clear, and it's a pretty non-standard usage of the operator.
It seems the primary advantage is that it's somewhat clever. I avoid clever unless there's a pretty good (external) reason to be clever.
我倾向于使用 switch 语句,因为编译器会捕获重复的情况。可以说,在这个例子中这不是一个问题,但如果列表变得非常长并且由几个不同的人处理,那么很容易添加重复项并且没有意识到这一点。
I would lean toward a switch statement because the compiler will catch duplicate cases. Arguably, this is not an issue in this example but if the list gets really long and is worked on by several different people it is easy to add a duplicate and not realize it.
仔细阅读 维基百科文章的 C++ 部分 。它明确列出了一些使用
?:
运算符是唯一选项的情况,并且不能用if/else
或switch
替代。另一方面,我不会仅仅因为它看起来更漂亮而使用它。
Read the C++ section of the Wikipedia article a bit more carefully. It explicitly lists some situations where using the
?:
operator is the only option, and can't be replaced byif/else
orswitch
.On the other hand, I wouldn't use it only because it looks prettier.
我以前从未见过这样写的东西。虽然它很聪明且格式良好,但这似乎是使用字典/哈希表的绝佳机会(假设
Vehicle
是一个枚举,这一点尚不清楚)。I've never seen anything written like this before. While it is clever and well-formatted, this seems like the perfect opportunity to use a dictionary/hashtable (assuming
Vehicle
is an enumeration, which is unclear).有些人已经提到了使用 std::map 或其他关联数组类型来完成这项工作的可能性。只要您只在一个地方(或几个地方)执行此操作,您可能会考虑仅使用普通数组或向量:取决于
您需要/使用的表(存储相同类型的对象)的数量,以及所包含对象的大小(在本例中为车辆),这可以是
std::map
的完美合理替代方案。如果您要创建很多表,或者每个对象都非常大,那么 std::map 会成为更合理的替代方案。当您使用
std::map
(或unordered_map
等)时,您将使用更多代码来节省数据存储。这会起到相反的作用——但只要 Vehicle 很小(比如 4 字节),像上面这样的一个表通常会占用大约半千字节。很难准确猜测特定编译器的 std::map 代码有多大,但看起来通常会大于一半一千字节,因此如果您只创建一个这样的表,std::map
可能会造成净损失。当然,如果你知道你只处理字母作为输入,你可以大大减少表的大小:
在示例中,这将给出一个大约 100 字节的表——你可以创建相当数量的表。
std::map
空间中的 100 字节表通常会占用。A few people have already mentioned the possibility of using an
std::map
or other associative array type to do the job. As long as you're only doing this is one place (or a few places), you might consider just using a normal array or vector instead:Depending on how may tables you need/use (that store the same type of object), and the size of the contained objects (Vehicle in this case), this can be a perfectly reasonable alternative to an
std::map
. If you're creating a lot of tables, or each object is really big,std::map
becomes a more reasonable alternative.When you use an
std::map
(orunordered_map
, etc.) you're using more code to save on data storage. This does the reverse -- but as long as Vehicle is small (say, 4 bytes), one table like the above will typically occupy something like half a kilobyte. It's hard to guess exactly how large the code forstd::map
is going to be for a specific compiler, but it seems likely that it'll usually be larger than half a kilobyte, so if you're only creating one table like this,std::map
may be a net loss.Of course, if you know that you're only dealing with letters as input, you could reduce the table size quite a bit:
In the example case, this would give a table around 100 bytes -- you can create a pretty fair number of 100-byte tables in the space
std::map
will normally occupy.纯粹实用:
加号: 三元序列更加灵活,可以用来避免
switch
的限制,可以使用其他运算符(例如<=、>) =) 或任何其他测试,包括字符串比较。此外,如果交换机是性能瓶颈并且概率不均匀,则可以强制首先执行最可能的测试(由于未评估未选择路径的保证)。
马马虎虎
与 switch 语句不同,顺序很重要(除非您坚持
==
)。这可能是一个优势,但在其他方面与 switch 类似,当维护者不熟悉这个概念或匆忙时可能会产生误导。许多开发人员可能会回避,因为他们不确定细节(将评估哪些术语,运算符的正确性好吗?) - 但是,如果您的开发人员池无法掌握一个很好的示例,您可能会禁止三元运算符无法解决的问题。
减号
它不像
switch
那样常见,因此优化器可能不会以相同的方式对待它。我们知道优化器会为开关选择最合适的实现(表、二分搜索、比较序列或它们的任意组合)。优化器无法重新排列我们的评估顺序,并且不太可能支持此处的表查找。需要良好的格式才能轻松识别(排列“?”和“:”) - 当您使用制表符时很糟糕。
美学
我喜欢它的精确性和简洁性,接近数学符号。然而,这也可能被用来对付它。这在代码审查中可能会让人大吃一惊,因为它不太常见而且更脆弱。
Purely practical:
Plus: The ternary sequence is more flexible, and can be used to avoid the limitations of
switch
, you could use other operators (e.g. <=, >=) or any other tests, including e.g. string comparisons.Also, if the switch is a performance bottleneck and you have uneven probabilities, you can force the likeliest tests being done first (due to the not evaluated guarantee for the path not chosen).
So-So
Unlike a switch statement, order is important (unless you stick to
==
). That can be an advantage, but being otherwise similar to switch that might be misleading when the maintainer is unfamiliar with the concept or in a hurry.Many developers may shy away because they aren't sure about the details (which terms will be evaluated, is the rpecedence of the operators ok?) - However, if your developer pool won't grasp a well-presented example, you might have problems that can't be solved by banning ternary operators.
Minus
It isn't as common as
switch
, thus the optimizer might not treat it the same. Optimizers are know to select the best fit implementation for a switch (table, binary search, comparison sequence, or any combination of this). Optimizers can't reaarange wevaluaiton order, and are less likely to support a table lookup here.Requires good formatting to be easily recognizable (lining up the '?' and ':') - Sucks when you use tabs.
Aesthetics
I like it for its precision and succinctness, close to mathematical notations. However, that might as well be used against it. It's probably an eyebrow raiser at code reviews, because it is less common and more brittle.
只是为了进行比较,在 C++0x 中,您可以在不使用条件运算符或外联函数的情况下获得表达式:
但实际上并没有更好。
Just for comparison, in C++0x you can have an expression without using the conditional operator or an out-of-line function:
Not really any better, though.
怎么样:
:-),顺便说一句。
How about:
:-), by the way.
我认为它对于编写代码的人很有用,但对于审阅者来说很难理解,
“保持简单,伙计”
I think its useful for someone who code it, but will be difficult to understand for the reviwer,
"KEEP IT SIMPLE BUDDY"
在我看来,由于示例的简单性,您所做的事情是可以接受的。如果您对每种情况都做更多的事情,这种类型的构造可能会很快变得混乱。出于这个原因,我更喜欢使用 switch 甚至嵌套 if then elses (如果没有太多情况),格式如下:
这是关于代码的可读性,这有助于代码的可维护性。我从来都不是条件运算符的超级粉丝,因为我不喜欢在一行上看到多个表达式。在调试器中单步执行代码时,条件运算符可能很难遵循。代码越简单,就越容易专注于代码的作用。
In my opinion what you've done is acceptable due to the simplicity of the example. If you were doing more things with each case this type of construct could rapidly get messy. For that reason I would prefer a switch or even nested if then elses (if there aren't too many cases), formatted as follows:
It's about the readability of the code, which lends itself to the maintainability of the code. I've never been a huge fan fan of the conditional operator, because I don't like to see multiple expressions on a single line. Conditional operators can be difficult to follow when single stepping the code in a debugger. The simpler the code the easier it is to concentrate on what the code is doing.
我们中的许多人都习惯了各种报告工具中的 Iif 函数或 Excel 中的 If 函数,我们基本上需要使用不太明确的 Iif(arg="B";"Bus";Iif(arg="A";飞机;“脚”))。相比之下,我更喜欢你的样品:)
我个人会使用 if-elses,但我对你的示例不会有任何问题。
Many of us are used to the Iif-functions in various reporting tools or the If-function in Excel where we basically need to use the less clear Iif(arg="B";"Bus";Iif(arg="A";Airplane;"Feet")). I love your sample compared to that :)
I personally would've used if-elses, but I would not have a problem with your sample.