if (i < input.size() - 1) print(0);
Bu döngüde optimize edilecek bir iş arkadaşına iddia ettim, böylece input.size()
her yinelemede okunmaz, ancak durum böyle değil!
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);
}
}
Gcc seçeneklerine sahip Derleyici Gezgini'ne göre -O3 -fno-exceptions
aslında input.size()
her bir yinelemeyi okuyor ve lea
çıkarma yapmak için kullanıyoruz !
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
İlginçtir, Rust'ta bu optimizasyon gerçekleşir. Her yinelemede azaltılmış i
bir değişkenle değiştirilmiş gibi görünüyor j
ve test i < input.size() - 1
gibi bir şeyle değiştiriliyor 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);
}
}
}
In Derleyici Explorer ilgili montaj şuna benzer:
cmpq %r12, %rbx
jae .LBB0_4
Kontrol ettim ve ben eminim r12
olduğunu xs.len() - 1
ve rbx
sayaç olduğunu. Daha önce bir add
for rbx
ve bir mov
dış döngü vardır r12
.
Bu neden? Görünüşe göre GCC satır içi yapabiliyorsa size()
ve operator[]
olduğu gibi, bunun size()
değişmediğini de bilmeli . Ama belki GCC'nin optimize edici, onu bir değişkene çekmeye değmeyeceğine karar verir? Ya da belki de bunu güvensiz hale getirecek başka bir olası yan etkisi vardır - kimse biliyor mu?
cout.operator<<()
. Derleyici, bu kara kutu işlevinin std::vector
bir genel öğeden bir başvuru almadığını bilmiyor .
println
ya operator<<
da anahtar olduğu konusunda haklısınız .
println
muhtemelen karmaşık bir yöntemdir, derleyiciprintln
vektörü değiştirmediğini kanıtlamakta sorun yaşayabilir .