※ 引述《ironstark (Stark)》之铭言:
: 不好意思想请问一下各位大大
: 两个function,a(),b(),回传bool
: X=a(),Y=b()
: 这样 if(X||Y)以及if(a()||b())两种写法在执行上会有什么差异呢?
: 这部分用到的观念是什么或是该搜寻什么关键字
: 小弟新手入门对一些细节不太熟悉,还请各位帮忙解惑,谢谢大家!
你可以尝试作实验画个真值表 (truth table) 来观察行为, 不过这代表我们
需要有办法决定 a()/b() 的回传值. 除了直接修改函式实作, 最快的方式就
是透过函式模板来作客制化:
template <bool B>
bool a() { std::cout << "a() "; return B; }
a<true>(); // print "a()", return true
a<false>(); // also print "a()", return false
a()/b() 都作一个模板我们就可以填完真值表内容:
┌──┬──┬────┐
│a() │b() │ output │
├──┼──┼────┤
│ F │ F │a() b() │
├──┼──┼────┤
│ F │ T │a() b() │
├──┼──┼────┤
│ T │ F │a() │
├──┼──┼────┤
│ T │ T │a() │
└──┴──┴────┘
范例: https://godbolt.org/z/TojhP5
从上表可以看到当 a() 回传值为 true 的时候, b() 就不会被呼叫. 一般人
可能会用short-circuit evaluation 来称呼它, 甚至撰写程式码的时候会依
赖这个行为 (为了写出主观简洁的程式码).
但小弟要在这里说: 这是不好的观念. 因为 C++ 允许使用者对运算子作重载
(overloading), 所有的重载版本 operator||() 以及 operator&&() 都没有
上面提到的short-circuit 行为. 我们可以将函式 a()/b() 改成回传列举型
别 Bool 来实验看看:
范例: https://godbolt.org/z/K1hGGf
因为 short-circuit 只作用在俗称内建型别 (primitive type) 算子上,
为了避免混淆, 有两派人马分别采取不同策略来避免预期以外的行为发生:
1. 一律不重载 operator&&() 及 operator||()
e.g. 《More Effective C++》Item #7
《C++FAQ》What are some guidelines / "rules of thumb"
for overloading operators?
2. 重载 operator&&() 及 operator||(), 但不对求值顺序/与否作假设
无论如何, 知道这些考量有助于写出更安全的程式. :)