if (i < input.size() - 1) print(0);
이 루프에서 최적화 input.size()
되어 모든 반복에서 읽히지 않는 동료에게 주장 했지만 이것이 사실이 아님을 알 수 있습니다!
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 옵션 이있는 컴파일러 탐색기 에 따르면 -O3 -fno-exceptions
실제로 input.size()
각 반복을 읽고 lea
빼기를 수행하는 데 사용 됩니다!
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
흥미롭게도 Rust에서이 최적화가 이루어집니다. 그것은과 같은 i
변수로 대체됩니다 j
각각의 반복을 감소하고, 시험은 i < input.size() - 1
같은 대체됩니다 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);
}
}
}
에서 컴파일러 탐색기 관련 어셈블리는 다음과 같습니다 :
cmpq %r12, %rbx
jae .LBB0_4
나는 확인하고 나는 확신 r12
입니다 xs.len() - 1
및 rbx
카운터입니다. 이전에는 add
for rbx
및 mov
외부 루프가 r12
있습니다.
왜 이런거야? GCC가 인라인 할 수 size()
있고 operator[]
마치 size()
변경되지 않는 것을 알 수 있어야합니다 . 그러나 GCC의 옵티마이 저는 변수로 가져올 가치가 없다고 판단합니까? 또는 이로 인해 안전하지 않은 다른 부작용이있을 수 있습니다.
cout.operator<<()
입니다. 컴파일러는이 블랙 박스 함수가 std::vector
전역에서 참조를 얻지 못한다는 것을 모른다 .
println
하거나 operator<<
핵심입니다.
println
복잡한 방법 일 수도 있습니다. 컴파일러는println
벡터를 변경하지 않는지 입증하는 데 문제가있을 수 있습니다 .