gpt4 book ai didi

c++ - 如何避免编写同一个循环的多个版本

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:14:24 25 4
gpt4 key购买 nike

在一个大循环中,我目前有一个类似于

的语句
if (ptr == NULL || ptr->calculate() > 5) 
{do something}

其中 ptr 是在循环之前设置的对象指针,并且从未更改过。

我想避免在循环的每次迭代中将 ptr 与 NULL 进行比较。 (当前的最终程序是这样做的,对吧?)一个简单的解决方案是为 (ptr == NULL) 和一次为 (ptr != NULL) 编写循环代码。但这会增加代码量,使其更难维护,而且如果同一个大循环出现两次而只更改一两行代码,这看起来很愚蠢。

我能做什么?也许使用动态值常量并希望编译器很聪明?怎么办?

非常感谢!

编辑 作者:Luther Blissett。 OP 想知道是否有更好的方法来删除此处的指针检查:

loop {
A;
if (ptr==0 || ptr->calculate()>5) B;
C;
}

比这里所示的复制循环:

if (ptr==0) 
loop {
A;
B;
C;
}
else loop {
A;
if (ptr->calculate()>5) B;
C;
}

最佳答案

我只是想通知您,显然 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();
}
}

用 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

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

关于c++ - 如何避免编写同一个循环的多个版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3319094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com