谁能解释这个简单逻辑背后的逻辑?我迷路了
Posted
技术标签:
【中文标题】谁能解释这个简单逻辑背后的逻辑?我迷路了【英文标题】:Can anyone explain the logic behind this simple logic? I'm lost 【发布时间】:2017-05-25 01:56:35 【问题描述】:我只是在 C++ 中尝试 do while 循环,而我想出了一个想法,即在 do while 循环中的 while 之后的括号内包含描述或任何名称,可以做多项事情。
所以这是我的初始逻辑:我已经设置了一个 password
变量和一个 input
变量。如果这两件事匹配,那么它将退出循环并输出“正确的密码”,否则它将继续返回循环,输出“错误的密码”等等。这是我的代码:
// do while
#include<iostream>
using namespace std;
int main()
int input, password=19960819;
do
cout << "Type your password:" ;
cin >> input;
while(input!=password && cout << "wrong password" << endl);
cout << "correct password" << endl;
return 0;
我期待即使我输入了正确的答案,我仍然会输出“错误密码”。我认为cout << "wrong password" << endl
部分将始终返回为true
,无论如何也应该执行,并且唯一的因素是input!=password
部分。然而,结果实际上是完美的,这不是我所期望的......谁能解释一下逻辑?我一直在挑战自己不要使用if
或其他逻辑,而只是使用do while
逻辑来达到这个结果,但我不明白它现在工作的原因......
【问题讨论】:
在您最喜欢的 C++ 书籍中了解&&
(和 ||
)的“短路”行为。
值得注意的是,如果你的逻辑期望两个语句都被执行,那么即使短路会导致错误,但对于其他事情来说真的很重要,比如能够做到if ((foo != nullptr) && (foo->bar()))
【参考方案1】:
C++ 将short-circuit evaluation 用于内置1 布尔运算符,这意味着当您这样做时:
A && B
仅当A
为true
时才计算B
,因为如果A
为false
,则整个表达式为false
(无论B
的值如何)。
所以在:
input != password && cout << "wrong password" << endl
当input != password
为false
时(输入正确密码时),第二个操作数cout << "wrong password" << endl
不求值,因此不输出任何内容。
条件评估的额外细节:
input != password
的类型是bool
;
cout << "..." << endl
的类型是std::ostream&
;
std::ostream
是 convertible to bool
直接(自 C++11 起)或使用转换为 void*
(C++03)。
由于没有operator&&(bool, [const] std::ostream&)
,并且std::ostream
可以转换为bool
,所以这里使用了内置的operator&&(bool, bool)
,所以应用短路评估2。
当input != password
为true
(您输入了错误的密码)时,cout << "..." << endl
被评估,然后转换为bool
值,大部分时间将由true
进行3,从而允许循环继续。
当input != password
为false
时,短路会阻止评估cout << "..." << endl
,并且不会将任何内容发送到输出。
1 对于重载的运算符,短路评估不再适用。见http://en.cppreference.com/w/cpp/language/operator_logical。
2 您可以在main
之前为&&
添加用户定义的重载,例如bool operator&&(bool b, std::ostream &s) return b && (bool)s;
,看到短路只适用于内置运算符。
3 不能保证这会返回true
,因为流可能处于失败状态,但对于std::cout
,这不太可能 .
【讨论】:
我会注意到短路只适用于内置类型,而不是当运算符重载时。 @FrançoisAndrieux:实际上只有当&&
过载时它才不再适用。
@Bathsheba 是 en.cppreference.com/w/cpp/language/operator_logical 不正确吗? "但重载运算符的行为类似于常规函数调用,并且总是计算两个操作数"
@CaptainGiraffe 你可以有一个内置类型,例如A
,可转换为bool
,因此A() && A()
将与非内置类型进行短路。
...正是这里发生了什么。最后,&&
始终是一个排序点。【参考方案2】:
cout << "wrong password" << endl
的计算结果始终为 true
(通过转换为 bool
运算符)并具有输出该文本的副作用。
但由于&&
的短路性质,这仅在input != password
时进行评估。
真的很可爱。不过就个人而言,我会写
while (input != password && std::cout << "wrong password\n");
请注意,这依赖于 std::basic_ios::operator bool
,它从 C++11 发生了微妙的变化。见http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool。在许多方面,最好避免使用这种华而不实的代码。
【讨论】:
谢谢@Bathsheba,现在一切都说得通了:)【参考方案3】:这是因为 && 和 ||在短路评估。因此,例如,如果 A 和 B 都(并且只有两者)都为真,则 A && B 将评估为真,但是(这里是短路)如果 A 或 B 为假,则它会为假,所以当 A 为假时,不需要评估B。
在您的场景中,当比较 'input!=password' 为 false(即 input == password)时,它会停止计算表达式。
希望这会有所帮助:)
对不起我的英语。
【讨论】:
谢谢,现在明白了~以上是关于谁能解释这个简单逻辑背后的逻辑?我迷路了的主要内容,如果未能解决你的问题,请参考以下文章