在一个大循环中,我目前有一个类似的声明
if (ptr == NULL || ptr->calculate() > 5)
{do something}
Run Code Online (Sandbox Code Playgroud)
其中ptr是在循环之前设置的对象指针,从不更改.
我想避免在循环的每次迭代中将ptr与NULL进行比较.(当前的最终程序就是这样做的,对吗?)一个简单的解决方案是为(ptr == NULL)编写一次循环代码,为(ptr!= NULL)编写一次.但这会增加代码量,使维护更加困难,而且如果相同的大循环出现两次只有一行或两行更改,则看起来很傻.
我能做什么?使用动态值常量可能并希望编译器是智能的?怎么样?
非常感谢!
由Luther Blissett 编辑.OP想要知道是否有更好的方法来删除指针检查:
loop {
A;
if (ptr==0 || ptr->calculate()>5) B;
C;
}
Run Code Online (Sandbox Code Playgroud)
比复制循环,如下所示:
if (ptr==0)
loop {
A;
B;
C;
}
else loop {
A;
if (ptr->calculate()>5) B;
C;
}
Run Code Online (Sandbox Code Playgroud)
我只是想通知你,显然GCC可以在优化器中执行此请求提升.这是一个模型循环(在C中):
struct C
{
int (*calculate)();
};
void sideeffect1();
void sideeffect2();
void sideeffect3();
void foo(struct C *ptr)
{
int i;
for (i=0;i<1000;i++)
{
sideeffect1();
if (ptr == 0 || ptr->calculate()>5) sideeffect2();
sideeffect3();
}
}
Run Code Online (Sandbox Code Playgroud)
用gcc 4.5和-O3编译它给出:
.globl foo
.type foo, @function
foo:
.LFB0:
pushq %rbp
.LCFI0:
movq %rdi, %rbp
pushq %rbx
.LCFI1:
subq $8, %rsp
.LCFI2:
testq %rdi, %rdi # ptr==0? -> .L2, see below
je .L2
movl $1000, %ebx
.p2align 4,,10
.p2align 3
.L4:
xorl %eax, %eax
call sideeffect1 # sideeffect1
xorl %eax, %eax
call *0(%rbp) # call p->calculate, no check for ptr==0
cmpl $5, %eax
jle .L3
xorl %eax, %eax
call sideeffect2 # ok, call sideeffect2
.L3:
xorl %eax, %eax
call sideeffect3
subl $1, %ebx
jne .L4
addq $8, %rsp
.LCFI3:
xorl %eax, %eax
popq %rbx
.LCFI4:
popq %rbp
.LCFI5:
ret
.L2: # here's the loop with ptr==0
.LCFI6:
movl $1000, %ebx
.p2align 4,,10
.p2align 3
.L6:
xorl %eax, %eax
call sideeffect1 # does not try to call ptr->calculate() anymore
xorl %eax, %eax
call sideeffect2
xorl %eax, %eax
call sideeffect3
subl $1, %ebx
jne .L6
addq $8, %rsp
.LCFI7:
xorl %eax, %eax
popq %rbx
.LCFI8:
popq %rbp
.LCFI9:
ret
Run Code Online (Sandbox Code Playgroud)
clang 2.7(-O3)也是如此:
foo:
.Leh_func_begin1:
pushq %rbp
.Llabel1:
movq %rsp, %rbp
.Llabel2:
pushq %r14
pushq %rbx
.Llabel3:
testq %rdi, %rdi # ptr==NULL -> .LBB1_5
je .LBB1_5
movq %rdi, %rbx
movl $1000, %r14d
.align 16, 0x90
.LBB1_2:
xorb %al, %al # here's the loop with the ptr->calculate check()
callq sideeffect1
xorb %al, %al
callq *(%rbx)
cmpl $6, %eax
jl .LBB1_4
xorb %al, %al
callq sideeffect2
.LBB1_4:
xorb %al, %al
callq sideeffect3
decl %r14d
jne .LBB1_2
jmp .LBB1_7
.LBB1_5:
movl $1000, %r14d
.align 16, 0x90
.LBB1_6:
xorb %al, %al # and here's the loop for the ptr==NULL case
callq sideeffect1
xorb %al, %al
callq sideeffect2
xorb %al, %al
callq sideeffect3
decl %r14d
jne .LBB1_6
.LBB1_7:
popq %rbx
popq %r14
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)