2014-04-10 43 views
1

假设您想要访问数组中的结构,并修改几个字段。你可以这样做的直接,如:引用和数组索引之间的任何区别?

units[unitIndex].field1 = value1; 
units[unitIndex].field2 = value2; 
units[unitIndex].field3 = value3; 
... 

或者,你可以拉至结构的引用,然后从那里修改它们:

unitStruct& unit = units[unitIndex]; 
unit.field1 = value1; 
unit.field2 = value2; 
unit.field3 = value3; 
... 

我一直认为第二种方法是“更好“,它不必每次都重新索引到数组中以重新查找结构。

但是当我停下来思考它时,我意识到编译器很可能将数组索引实现为指针。而且这个参考也可能作为一个指针来实现。也许他们在内部也在做同样的事情?

所以我想知道的是,从编译器的角度来看,生成的代码,这两种方法之间有什么真正的区别?编译器是否为这些方法之一生成任何额外的代码,或者它们本质上是获得完全相同结果的两种方法?

回答

2

当启用优化编译时,编译器会以任何方式生成相同的代码,您应该使用任何样式使代码对您和维护代码的人更易读。

例如

#include <cstddef> 
#include <vector> 

struct unitStruct { 
    int field1; 
    int field2; 
    int field3; 
}; 

void noref(std::vector<unitStruct> & units, size_t unitIndex, int value1, int value2, int value3) 
{ 
    units[unitIndex].field1 = value1; 
    units[unitIndex].field2 = value2; 
    units[unitIndex].field3 = value3; 
} 

void ref(std::vector<unitStruct> & units, size_t unitIndex, int value1, int value2, int value3) 
{ 
    unitStruct& unit = units[unitIndex]; 
    unit.field1 = value1; 
    unit.field2 = value2; 
    unit.field3 = value3; 
} 

用gcc编译和优化启用-O3

g++ -O3 -c struct.cpp -o struct.o 
objdump -D struct.o|less 

生成相同的代码 - 前三个指令出现在不同的顺序,但仅此而已:

0000000000000000 <_Z5norefRSt6vectorI10unitStructSaIS0_EEmiii>: 
    0: 48 8d 04 76    lea (%rsi,%rsi,2),%rax 
    4: 48 8b 37    mov (%rdi),%rsi 
    7: 48 8d 04 86    lea (%rsi,%rax,4),%rax 
    b: 89 10     mov %edx,(%rax) 
    d: 89 48 04    mov %ecx,0x4(%rax) 
    10: 44 89 40 08    mov %r8d,0x8(%rax) 
    14: c3      retq 

0000000000000020 <_Z3refRSt6vectorI10unitStructSaIS0_EEmiii>: 
    20: 4c 8b 0f    mov (%rdi),%r9 
    23: 48 8d 04 76    lea (%rsi,%rsi,2),%rax 
    27: 49 8d 04 81    lea (%r9,%rax,4),%rax 
    2b: 89 10     mov %edx,(%rax) 
    2d: 89 48 04    mov %ecx,0x4(%rax) 
    30: 44 89 40 08    mov %r8d,0x8(%rax) 
    34: c3      retq 
+0

您应该注意在-O3中启用了优化。 –

+0

@RobK好点,我会强调这一点,谢谢。 – amdn

0

我几乎不相信有什么区别。 units[unitIndex]会给你一个unitStruct &。

我认为唯一的区别是有人阅读代码。

1

在调试模式下,编译器可以生成不同的代码。对于单位[unitIndex],它可以计算每行的单位+单位索引指针。如果您使用参考,偏移量将被计算一次,并存储在堆栈中。

在经过优化的版本中,在这两种情况下,编译器可能会执行一次计算并将计算出的偏移量保存在寄存器中。

重要的是,它更可读,更易于维护。当你为一件事情进行优化时,你会为其他事情感到悲观。在几乎所有情况下,您都应该优化可读性和可维护性。

[ETA]如果您真的对差异感到好奇,可以让编译器将生成的程序集写入文件。有关如何执行此操作,请参阅编译器的帮助。

相关问题