Saya mengklaim rekan kerja yang if (i < input.size() - 1) print(0);akan dioptimalkan dalam lingkaran ini sehingga input.size()tidak dibaca di setiap iterasi, tetapi ternyata ini bukan masalahnya!
void print(int x) {
std::cout << x << std::endl;
}
void print_list(const std::vector<int>& input) {
int i = 0;
for (size_t i = 0; i < input.size(); i++) {
print(input[i]);
if (i < input.size() - 1) print(0);
}
}
Menurut Compiler Explorer dengan opsi gcc, -O3 -fno-exceptionskami sebenarnya membaca input.size()setiap iterasi dan menggunakan leauntuk melakukan pengurangan!
movq 0(%rbp), %rdx
movq 8(%rbp), %rax
subq %rdx, %rax
sarq $2, %rax
leaq -1(%rax), %rcx
cmpq %rbx, %rcx
ja .L35
addq $1, %rbx
Menariknya, di Rust optimasi ini memang terjadi. Sepertinya iakan diganti dengan variabel jyang dikurangi setiap iterasi, dan tes i < input.size() - 1diganti dengan sesuatu seperti j > 0.
fn print(x: i32) {
println!("{}", x);
}
pub fn print_list(xs: &Vec<i32>) {
for (i, x) in xs.iter().enumerate() {
print(*x);
if i < xs.len() - 1 {
print(0);
}
}
}
Di Penjelajah Kompiler , rakitan yang relevan terlihat seperti ini:
cmpq %r12, %rbx
jae .LBB0_4
Aku memeriksa dan saya cukup yakin r12adalah xs.len() - 1dan rbxadalah meja. Sebelumnya ada addfor rbxdan di movluar loop ke r12.
Kenapa ini? Sepertinya jika GCC mampu menyejajarkan size()dan operator[]seperti yang terjadi, itu harus bisa tahu bahwa size()tidak berubah. Tapi mungkin pengoptimal GCC menilai bahwa tidak layak menariknya ke dalam variabel? Atau mungkin ada beberapa efek samping lain yang mungkin membuat ini tidak aman - adakah yang tahu?
cout.operator<<(). Kompiler tidak tahu bahwa fungsi kotak hitam ini tidak mendapatkan referensi ke std::vectordari global.
printlnatau operator<<kuncinya.
printlnmungkin metode yang kompleks, compiler mungkin mengalami kesulitan pembuktian bahwaprintlntidak bermutasi vektor.