如果我们在c ++中有以下2段代码执行相同的任务:
int a, b=somenumber;
while(b > 0)
{
a = b % 3;
b /= 3;
}
或
int b=somenumber;
while(b > 0)
{
int a=b%3;
b /= 3;
}
我对计算机体系结构/ c ++设计了解不多,但我认为第一个代码更快,因为它在开始时声明了整数a并且只在while循环中使用它,而在第二个代码中每次while循环重新开始时都会声明整数a。有人可以帮助我,我是正确的还是为什么?为什么?
答案 0 :(得分:14)
应该没有区别,但是要进行额外的经验(肛门?)我用g ++测试了它,为每个代码片段创建了一个函数。无论有无优化,无论int a
声明在何处,它都会生成相同的代码。
#include <iostream>
int variant_a(int b)
{
int a;
while(b > 0)
{
a = b % 3;
b /= 3;
}
return b;
}
int variant_b(int b)
{
while(b > 0)
{
int a = b % 3;
b /= 3;
}
return b;
}
int main()
{
std::cout << variant_a(42) << std::endl;
std::cout << variant_b(42) << std::endl;
}
这是未经优化的循环:
_Z9variant_ai:
.LFB952:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $24, %esp
.LCFI2:
jmp .L2
.L3:
movl 8(%ebp), %eax
movl %eax, -20(%ebp)
movl $1431655766, -24(%ebp)
movl -24(%ebp), %eax
imull -20(%ebp)
movl %edx, %ecx
movl -20(%ebp), %eax
sarl $31, %eax
subl %eax, %ecx
movl %ecx, %eax
addl %eax, %eax
addl %ecx, %eax
movl -20(%ebp), %edx
subl %eax, %edx
movl %edx, %eax
movl %eax, -4(%ebp)
movl 8(%ebp), %eax
movl %eax, -20(%ebp)
movl $1431655766, -24(%ebp)
movl -24(%ebp), %eax
imull -20(%ebp)
movl %edx, %ecx
movl -20(%ebp), %eax
sarl $31, %eax
movl %ecx, %edx
subl %eax, %edx
movl %edx, %eax
movl %eax, 8(%ebp)
.L2:
cmpl $0, 8(%ebp)
jg .L3
movl 8(%ebp), %eax
leave
ret
和优化的一个:
_Z9variant_ai:
.LFB968:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
pushl %ebx
.LCFI2:
movl 8(%ebp), %ebx
testl %ebx, %ebx
jle .L2
movl $1431655766, %ecx
.p2align 4,,7
.p2align 3
.L5:
movl %ebx, %eax
imull %ecx
movl %ebx, %eax
sarl $31, %eax
movl %edx, %ebx
subl %eax, %ebx
jne .L5
.L2:
movl %ebx, %eax
popl %ebx
popl %ebp
ret
答案 1 :(得分:11)
int声明是编译器的信息,不会转换为必须编码的指令。所以没有区别。在循环内声明int不会使循环向下倾斜。为什么不尝试自己编译并让编译器输出汇编代码,以便您自己查看。
答案 2 :(得分:4)
说真的,这真的很重要吗?这是您应该尝试避免的微优化类型。编写更易读的代码,恕我直言是第二个循环。编译器足以对这些类型的事情进行优化,我会留下它来做。
答案 3 :(得分:2)
除了标准库中的性能保证之外,C ++标准中没有“更快”。优化编译器可能会消除a
,因为它没有被使用。或者,它可以同时为所有局部变量分配所需的所有内存函数,然后它也不会有任何区别。
关于这种低级语言结构的唯一合理问题是你的特定实现是更快还是更慢地运行它们,找到它的最好方法是自己计时。您会发现很多这些事情并不重要,如果您检查生成的代码,您会发现编译器使用不同的编写代码的方式做同样的事情。
通常,寻找微观优化是一个坏主意,但如果您尝试设置一般风格,则可能值得(例如,使用++i
而不是i++
) 。但是,如果您为可读性之外的任何目的设置样式,则应该有充分的理由这样做。在这种情况下,这意味着测试性能。
答案 4 :(得分:1)
不,它不能在循环中“声明”,因为它是在编译时声明的。我会说它们是相同的,但如果变量的类型更复杂,那么第二个可能会更快,具有构造函数和析构函数。
答案 5 :(得分:1)
理论上,第一个选项可能更快。在实践中,我希望将a和b放入寄存器中,使生成的程序集相同(可以在编译的二进制文件中验证)。如果你执行循环足够多次,你认为可能存在差异,唯一的方法就是测量。如果您的探查器无法区分,请以使代码对未来维护者最清晰的方式对其进行编码。
一般而言(如前所述),这些类型的优化不会在程序性能方面提供任何有意义的改进。您应该寻找算法和设计优化。
答案 6 :(得分:0)
我不相信在练习中会有任何不同。没有涉及内存分配,因为自动变量的内存在编译时被分配或保留。
理论上我认为第二个也可以更快:编译器有更多关于变量在何处以及如何使用的信息(例如,你可能会重复使用相同的变量来处理以后完全不相关的变量)。
当您处理构建昂贵的类型时,您可能会开始担心这些问题。例如,我应该在内部循环中声明一个std :: vector,还是应该在循环之前声明它并在循环体的开头clear()
声明它(重用已分配的内存)。
答案 7 :(得分:-6)
第一个应该更快;然而,编译器通常足够聪明,可以自行优化,所以可能无关紧要。
虽然纯粹,但答案是第一个
编辑:它更快,因为它只需要一个分配而不是N(N是while循环将执行的迭代次数)。