Pertanyaan wawancara: Mana yang akan mengeksekusi lebih cepat, if (flag==0)atau if (0==flag)? Mengapa?
if(flag = 0)dengan harga sedikit keterbacaan.
Pertanyaan wawancara: Mana yang akan mengeksekusi lebih cepat, if (flag==0)atau if (0==flag)? Mengapa?
if(flag = 0)dengan harga sedikit keterbacaan.
Jawaban:
Saya belum melihat jawaban yang benar (dan sudah ada beberapa) peringatan: Nawaz memang menunjukkan jebakan yang ditentukan pengguna . Dan saya menyesal karena terburu-buru memberikan suara positif pada "pertanyaan paling bodoh" karena tampaknya banyak yang tidak menjawabnya dengan benar dan ini memberi ruang untuk diskusi yang bagus tentang pengoptimalan kompiler :)
Jawabannya adalah:
Apa
flagtipenya?
Dalam kasus di mana flagsebenarnya adalah tipe yang ditentukan pengguna. Kemudian tergantung pada overload mana yang operator==dipilih. Tentu saja terlihat bodoh bahwa mereka tidak akan simetris, tetapi itu pasti diperbolehkan, dan saya sudah melihat pelanggaran lain.
Jika flagbuilt-in, maka keduanya harus mengambil kecepatan yang sama.
Dari artikel Wikipedia pada x86, saya berani bertaruh untuk Jxxinstruksi untuk ifpernyataan: mungkin JNZ(Langsung jika Tidak Nol) atau setara.
Saya ragu kompilator melewatkan optimasi yang begitu jelas, bahkan dengan optimasi dimatikan. Ini adalah jenis hal yang dirancang untuk Pengoptimalan Lubang intip .
EDIT: Munculkan lagi, jadi mari tambahkan beberapa assembly (LLVM 2.7 IR)
int regular(int c) {
if (c == 0) { return 0; }
return 1;
}
int yoda(int c) {
if (0 == c) { return 0; }
return 1;
}
define i32 @regular(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
define i32 @yoda(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
Bahkan jika seseorang tidak tahu cara membaca IR, saya pikir itu sudah cukup jelas.
flagpasti bilangan bulat atau boolean. OTOH, memiliki variabel bernama flagdari tipe yang ditentukan pengguna cukup salah pada dirinya sendiri, IMHO
#includepetunjuk pun . Untuk mudahnya, biasanya sebesar int, char, booldan sejenisnya. Semua jenis lain dikatakan user-defined, yaitu mereka ada karena mereka adalah hasil dari beberapa pengguna menyatakan mereka: typedef, enum, struct, class. Misalnya, std::stringadalah ditentukan pengguna, meskipun Anda pasti tidak mendefinisikannya sendiri :)
Kode yang sama untuk amd64 dengan GCC 4.1.2:
.loc 1 4 0 # int f = argc;
movl -20(%rbp), %eax
movl %eax, -4(%rbp)
.loc 1 6 0 # if( f == 0 ) {
cmpl $0, -4(%rbp)
jne .L2
.loc 1 7 0 # return 0;
movl $0, -36(%rbp)
jmp .L4
.loc 1 8 0 # }
.L2:
.loc 1 10 0 # if( 0 == f ) {
cmpl $0, -4(%rbp)
jne .L5
.loc 1 11 0 # return 1;
movl $1, -36(%rbp)
jmp .L4
.loc 1 12 0 # }
.L5:
.loc 1 14 0 # return 2;
movl $2, -36(%rbp)
.L4:
movl -36(%rbp), %eax
.loc 1 15 0 # }
leave
ret
Tidak akan ada perbedaan dalam versi Anda.
Saya berasumsi bahwa typeflag bukanlah tipe yang ditentukan pengguna, melainkan beberapa tipe bawaan. Enum adalah pengecualian! . Anda dapat memperlakukan enum seolah-olah itu ada di dalamnya. Faktanya, nilai itu adalah salah satu tipe bawaan!
Dalam kasus, jika itu tipe yang ditentukan pengguna (kecuali enum), maka jawabannya sepenuhnya tergantung pada bagaimana Anda membebani operator ==. Perhatikan bahwa Anda telah membebani ==dengan mendefinisikan dua fungsi, satu untuk setiap versi Anda!
Sama sekali tidak ada perbedaan.
Anda mungkin mendapatkan poin dalam menjawab pertanyaan wawancara itu dengan merujuk pada penghapusan kesalahan ketik tugas / perbandingan, meskipun:
if (flag = 0) // typo here
{
// code never executes
}
if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}
Meskipun benar, misalnya kompilator-C memang memperingatkan dalam kasus yang sebelumnya ( flag = 0), tidak ada peringatan seperti itu di PHP, Perl atau Javascript atau <insert language here>.
Sama sekali tidak akan ada perbedaan dalam hal kecepatan. Kenapa harus ada?
x == 0mungkin menggunakannya tetapi 0 == xmungkin menggunakan perbandingan normal. Saya memang mengatakan itu harus terbelakang.
virtual operator==(int)tipe yang ditentukan pengguna?
Ada perbedaan ketika flag adalah tipe yang ditentukan pengguna
struct sInt
{
sInt( int i ) : wrappedInt(i)
{
std::cout << "ctor called" << std::endl;
}
operator int()
{
std::cout << "operator int()" << std::endl;
return wrappedInt;
}
bool operator==(int nComp)
{
std::cout << "bool operator==(int nComp)" << std::endl;
return (nComp == wrappedInt);
}
int wrappedInt;
};
int
_tmain(int argc, _TCHAR* argv[])
{
sInt s(0);
//in this case this will probably be faster
if ( 0 == s )
{
std::cout << "equal" << std::endl;
}
if ( s == 0 )
{
std::cout << "equal" << std::endl;
}
}
Dalam kasus pertama (0 == s) operator konversi dipanggil dan kemudian hasil yang dikembalikan dibandingkan dengan 0. Dalam kasus kedua operator == dipanggil.
Jika ragu, tandai dan pelajari kebenaran.
Mereka harus persis sama dalam hal kecepatan.
Namun perhatikan bahwa beberapa orang menggunakan konstanta di sebelah kiri dalam perbandingan persamaan (yang disebut "Yoda conditional") untuk menghindari semua kesalahan yang mungkin muncul jika Anda menulis =(operator penugasan) dan bukan ==(operator perbandingan persamaan); karena menugaskan ke literal memicu kesalahan kompilasi, kesalahan semacam ini dihindari.
if(flag=0) // <--- typo: = instead of ==; flag is now set to 0
{
// this is never executed
}
if(0=flag) // <--- compiler error, cannot assign value to literal
{
}
Di sisi lain, kebanyakan orang menganggap "Yoda conditionals" tampak aneh dan menjengkelkan, terutama karena kelas kesalahan yang mereka cegah dapat dilihat juga dengan menggunakan peringatan kompiler yang memadai.
if(flag=0) // <--- warning: assignment in conditional expression
{
}
Seperti yang dikatakan orang lain, tidak ada perbedaan.
0harus dievaluasi. flagharus dievaluasi. Proses ini membutuhkan waktu yang sama, tidak peduli di sisi mana mereka ditempatkan.
Jawaban yang tepat adalah: keduanya memiliki kecepatan yang sama.
Bahkan ekspresi if(flag==0)dan if(0==flag)jumlah karakternya sama! Jika salah satunya ditulis sebagai if(flag== 0), maka kompilator akan memiliki satu ruang ekstra untuk diurai, jadi Anda akan memiliki alasan yang sah untuk menunjukkan waktu kompilasi.
Tetapi karena tidak ada hal seperti itu, sama sekali tidak ada alasan mengapa seseorang harus lebih cepat dari yang lain. Jika ada alasannya, maka kompilator melakukan beberapa hal yang sangat, sangat aneh untuk membuat kode ...
Puasa mana yang tergantung pada versi == yang Anda gunakan. Berikut cuplikan yang menggunakan 2 kemungkinan penerapan ==, dan bergantung pada apakah Anda memilih untuk memanggil x == 0 atau 0 == x salah satu dari 2 dipilih.
Jika Anda hanya menggunakan POD, ini seharusnya tidak menjadi masalah dalam hal kecepatan.
#include <iostream>
using namespace std;
class x {
public:
bool operator==(int x) { cout << "hello\n"; return 0; }
friend bool operator==(int x, const x& a) { cout << "world\n"; return 0; }
};
int main()
{
x x1;
//int m = 0;
int k = (x1 == 0);
int j = (0 == x1);
}
Baiklah, saya setuju sepenuhnya dengan semua yang dikatakan di komentar kepada OP, demi latihan:
Jika kompilator tidak cukup pintar (memang Anda tidak boleh menggunakannya) atau pengoptimalan dinonaktifkan, x == 0dapat dikompilasi ke jump if zeroinstruksi perakitan asli , sementara itu 0 == xbisa menjadi perbandingan nilai numerik yang lebih umum (dan mahal).
Tetap saja, saya tidak ingin bekerja untuk bos yang berpikir seperti ini ...
Pastinya tidak ada perbedaan dalam hal kecepatan eksekusi. Kondisi tersebut perlu dievaluasi pada kedua kasus dengan cara yang sama.
Saya pikir jawaban terbaik adalah "dalam bahasa apa contoh ini"?
Pertanyaan tidak menentukan bahasanya dan diberi tag 'C' dan 'C ++'. Jawaban yang tepat membutuhkan lebih banyak informasi.
Ini adalah pertanyaan pemrograman yang buruk, tetapi bisa juga bagus dalam departemen "mari beri orang yang diwawancarai cukup tali untuk menggantung diri atau membangun ayunan pohon" yang licik. Masalah dengan pertanyaan semacam itu adalah biasanya mereka ditulis dan diturunkan dari pewawancara ke pewawancara hingga sampai ke orang-orang yang tidak benar-benar memahaminya dari semua sudut.
Buat dua program sederhana menggunakan cara yang disarankan.
Kumpulkan kodenya. Lihatlah majelis dan Anda bisa menilai, tapi saya ragu ada perbedaannya!
Wawancara semakin rendah dari sebelumnya.
Sekadar tambahan (menurut saya kompiler yang layak akan membuat pertanyaan ini diperdebatkan, karena ini akan mengoptimalkannya) menggunakan 0 == flag over flag == 0 memang mencegah kesalahan ketik di mana Anda lupa salah satu dari = (yaitu jika Anda tidak sengaja mengetik flag = 0 itu akan dikompilasi, tetapi 0 = flag tidak akan), yang menurut saya adalah kesalahan yang dilakukan semua orang pada satu titik atau lainnya ...