標籤:

C++中if(a!=b)和if(a^b)哪個效率更高?

C++中if(a!=b)和if(a^b)哪個效率更高?

沒有重載運算符

^是XOR

!=是不等於


不要瞎j8優化,編譯器比你清楚哪條彙編更快

隨便舉個例子


你要相信編譯器在不同平台、不同數據類型時,能替你生成最優的目標碼。

只有一些較複雜的情況下,你知道一些額外的信息(而編譯器是不知道的),才需要手工做這類優化。(2017/12/15更新)例如 [1] §7.5 提出了關於 boolean 運算的問題及優化。

[1] Fog, Agner. "Optimizing software in C++." http://www.agner.org/optimize/optimizing_cpp.pdf


曾經有這麼一個問題,有人在討論:在 C/C++ 中,把整型變數 a 乘以 2 怎樣寫比較快。是寫作 a * 2 還是 a &<&< 1 呢?或者還有其他寫法嗎?然後,底下一堆人給了各種奇技淫巧。直到有一個人跳出來說:直接寫作 a * 2 即可;如果你發現有其他寫法比這樣更快,那麼把實現編譯器的人拖出來打一頓就好了。

你要相信編譯器,不要自己去做所謂的「優化」。代碼是寫給人看的,只有在極其必要的情況下,才需要這些奇技淫巧。

對於你的問題,你可以對比一下彙編(這是個好網站:Compiler Explorer - C++)。

#include &
#include &

int main() {
int a = std::rand();
int b = std::rand();
if (a != b) {
std::cout &<&< a + b &<&< std::endl; } a = std::rand(); b = std::rand(); if (a ^ b) { std::cout &<&< a - b &<&< std::endl; } return 0; }

x86_64 下 gcc 7.2 開優化 -O3 給出的結果是

main:
push rbx
call rand
mov ebx, eax
call rand
cmp ebx, eax
je .L2
lea esi, [rbx+rax]
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream& &>::operator&<&<(int) mov rdi, rax call std::basic_ostream& &> std::endl& &>(std::basic_ostream& &>)
.L2:
call rand
mov ebx, eax
call rand
cmp ebx, eax
je .L3
mov esi, ebx
mov edi, OFFSET FLAT:std::cout
sub esi, eax
call std::basic_ostream& &>::operator&<&<(int) mov rdi, rax call std::basic_ostream& &> std::endl& &>(std::basic_ostream& &>)
.L3:
xor eax, eax
pop rbx
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:std::__ioinit
call std::ios_base::Init::Init()
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:std::__ioinit
mov edi, OFFSET FLAT:std::ios_base::Init::~Init()
add rsp, 8
jmp __cxa_atexit

兩種寫法編譯器給出的結果都是 cmp ebx, eax。

因此,兩種寫法一樣。



哎,那個。。。雖然樓上高票回答里講的道理我都同意,但是那個截圖的例子真的不太好。

萬一碰到一個有 icc 信仰的人,那就很尷尬了。


哈,就喜歡這種無法抖書袋子的問題!!

首先答主開始注意到這些問題了,說明是時候認真學一學彙編語言了,不然你明白了具體這個問題,還會有數不清的問題。比如交換倆變數值,是用第三個臨時變數快?還是用三次異或快?再比如為什麼當函數真的被內聯(inline)了後就會更快些?等等。這些問題,你懂了彙編之後,自己這個小程序編譯一下去看listing,或者在調試器里讓它顯示反彙編,就一目了然了。

其次正面回答具體這個問題。要我說,if(a!=b)快 —— 不是機器運行的更快,而是讓別人看你的程序時更快,機器上絲毫差別沒有。

C/C++好歹也是高級語言,其產生的初衷就是讓人跟機器說人話,從而你更清楚自己在說什麼,我也能更快更好的明白你腦子裡在想什麼,從而解放生產力發展生產力。if a !=b then do sth.就是人話。但你非把它寫成if a^b就使這個初衷大打折扣了。


肯定是一樣的,不然實現編譯器的人就被打死了


真對指令級別性能感興趣,你應該去看《計算機體系結構量化研究方法》、編譯器後端優化的書比如《高級編譯器設計》,然後去琢磨特定cpu比如intel的優化手冊。只有對cpu的微結構和編譯器優化技術有初步了解才能真搞懂這些性能問題。如果對計算機的理解只有二進位、彙編語言比c語言快C語言比c++快,問一百個這樣的問題也是江湖。


如果你只是在一個很普通的代碼里見到後面if(a^b)這種寫法,那麼你可以大膽地修改成前面的if(a!=b),然後去diss那個寫代碼的人了。這個例子就是典型的矯枉過正。

高級語言,首先是寫給人看的。


效率相同

使用不等於符號的可讀性更強

不要xjb優化,該做的優化編譯器都幫你做完了


還是以可讀性優先吧


答案:不知道,或者說,看情況而定

情況一:對於 int long 等這種整數型(浮點型不清楚)的來說,好的編譯器應該可以將這兩種操作優化成一樣快的(還要看目標平台的要求,但至少 x86 和 amd64 平台是這樣的),永遠不要懷疑編譯器的優化能力。

情況二:!= 與 ^ 被重載過,此時就要看重載函數的具體實現了,不同的實現會帶來不同的結果,所以答案是不知道。

極端一點,舉個例子,比如 != 的重載函數只有一句 return true 而 ^ 的重載函數需要對一個圖像進行處理,那不管編譯器怎麼優化,!= 肯定比 ^ 快。


如果是大家維護的代碼誰要寫後面那種我乾死他


編譯器比想像的要聰明,很多情況下無論你怎麼寫,他都會轉化成最快捷的方式,可能很久以前編譯器還沒有一些優化的時候,程序員需要憋這種奇淫巧技來優化,到現在還這麼用的,說實話不是看的書太舊了,就是想炫技的…


恩,編譯器絕大部分比你想像的要聰明。

哪個效率更高,得通過測試說話。


1.這兩種寫法,第一種更好讀好理解.可讀性和可維護性比微小的效率更重要一些.

2.沒有規定a和b類型的情況下,這兩種寫法並不等同.

3.如果a和b重載了!=和^運算符, 那結果更加不一定.


其實一個工程中需要提高的地方太多,以至於這種級別的優化根本不需要!多花點時間在演算法和程序架構上比這種炫技似的優化要實際的多。


如果你不是單幹的,相比於這種trick上的優化,代碼的可讀性是更為重要的。

如果就是想炫技,也不在乎他人是否看得懂,那自己開心就好。


我是來忽悠噠。

大部分時候,你希望你高估了編譯器的能力,但是更多的時候,你還是低估了編譯器。

屬於哪層的回哪去,回不去插一腿就插的帥似的。

跑用例看彙編哇


高級語言的代碼給人看,機器碼才是給機器看的


推薦閱讀:

如何設計一個真正高性能的spin_lock?
使用C++的痛苦來自哪裡?
最近在Oulu進行的關於c++17標準的會議有什麼進展?
c++開發轉向go開發是否是一個好的發展方向?
這個求指數函數exp()的快速近似方法的原理是什麼?

TAG:C |