2010-04-15 64 views
9

也许这是一个编译器特定的事情。如果是这样,gcc(g ++)怎么样?如果使用这样的变量引用/别名:变量引用(别名)是否会导致运行时成本?

int x = 5; 
int& y = x; 
y += 10; 

它实际上需要比,如果我们没有使用参考以上的周期。

int x = 5; 
x += 10; 

换句话说,做机器代码的变化,还是在“别名”在编译器级别只发生?

这可能看起来像一个愚蠢的问题,但我很好奇。特别是在可能暂时重命名某些成员变量以方便数学代码更易于阅读的情况下。当然,我们并不是在说这里的瓶颈......但是这是我正在做的事情,所以我只是想知道是否存在“实际”差异......或者只是表面上的差异。

回答

9

它可以被视为别名,但不是效率。在引擎盖下面,引用是一个具有更好语法和更高安全保证的指针。因此,你有一个“取消引用”操作运行时惩罚。除非编译器优化它,但我不会指望通常。

在编译器是否优化它的问题的情况下,除了查看生成的程序集外没有别的办法。

+0

很好的答案。谢谢 – cheshirekow 2010-04-15 00:30:21

+4

答案并不完全准确。引用背后的意图之一是实现别名的概念,即现有对象的替代名称。我相信这是在TC++ PL中明确陈述的。尽管情况并非总是如此,但“别名”仍然是许多情况下参考文献的准确描述。 – AnT 2010-04-15 00:32:20

+0

@AndreyT,我从来没有听说过引用是别名的想法,你能否在这里标明标准的段落? – 2010-04-15 00:35:08

4

确切知道的唯一方法是编译它并检查编译器的输出。通常,引用的开销类似于指针的开销,因为指针通常是如何实现引用的。然而,鉴于你正在展示的简单案例,我相信这个参考将被优化掉。

+0

是的,我可能有一天会做一些简单的测试,看看它是否被优化出来......现在,它不是太重要。 – cheshirekow 2010-04-15 00:31:35

0

是的,取消引用后面的指针引起额外的运行时成本,但可能不重要。以任何最清晰的方式编写代码,并最干净地表达您所瞄准的语义,然后在性能问题时运行在分析器中(瓶颈几乎不是您猜测的)。如果你在MacOS上,Shark是太棒了。

+0

完成。就像我说的,只是好奇。在Mac上开发? ew ...;) – cheshirekow 2010-04-15 00:32:21

+0

不要怠慢你不知道的东西! :-)调试和分析工具是一流的,不需要$$$。 – metasim 2010-04-15 01:34:57

+0

这个答案是错误的。 – 2015-11-25 18:34:25

4

的确,在大多数情况下,引用实现了“别名”的概念,这是他们绑定对象的替代名称。

但是,通常情况下引用是通过指针实现的。尽管如此,一个好的编译器只会在实际绑定在运行时确定的情况下使用实际指针来实现引用。如果在编译时已知绑定(和类型匹配),编译器通常将引用作为同一对象的替代名称,在这种情况下,通过引用访问对象不会有性能损失(与访问相比它通过它的原名)。

你的例子就是其中的一种,当你不应该引用性能损失时。

4

这两个函数都编译成g++中的完全相同的代码,即使只是使用-O1。 (我添加了return声明以确保计算没有完全消除。)

没有指针,只有一个引用。在这个微不足道的例子中,没有性能差异。尽管如此,这并不能保证对于所有参考用途来说,情况总是如此(没有性能差异)。

int f() 
{ 
    int x = 5; 
    x += 10; 
    return x; 
} 

int f() 
{ 
    int x = 5; 
    int & y = x; 
    y += 10; 
    return y; 
} 

汇编:

movl $15, %eax 
ret 
+1

不确定这是一个公平的测试,因为如您的结果所示,函数的整个主体可以在编译时进行评估。 – 2010-04-15 00:52:14

+1

@Daniel Pryden:但这是被问到的代码。你能提出一个更公平的测试代码吗? – 2010-04-15 01:01:15

+0

我认为我的测试更公平一些,因为编译器在编译时没有评估主体。 (但我没有测试相同的代码)。 – 2015-07-17 15:27:42

2

我比较2层的程序在GNU/Linux。下面仅显示GCC输出,但是叮声结果导致相同的结论。

GCC版本:4.9.2

锵版本:3.4.2

的程序

1.cpp

#include <stdio.h> 
int main() 
{ 
    int x = 3; 
    printf("%d\n", x); 
    return 0; 
} 

2.cpp

#include <stdio.h> 
int main() 
{ 
    int x = 3; 
    int & y = x; 
    printf("%d\n", y); 
    return 0; 
} 

测试

尝试1:无优化

gcc -S --std=c++11 1.cpp

gcc -S --std=c++11 2.cpp

1.cpp的所得的组件是短。

尝试2:

gcc -S -O2 --std=c++11 1.cpp

gcc -S -O2 --std=c++11 2.cpp

所得到的组件是优化完全相同。

的组件输出

1.cpp,没有优化

.file "1.cpp" 
    .section .rodata 
.LC0: 
    .string "%d\n" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    subq $16, %rsp 
    movl $3, -4(%rbp) 
    movl -4(%rbp), %eax 
    movl %eax, %esi 
    movl $.LC0, %edi 
    movl $0, %eax 
    call printf 
    movl $0, %eax 
    leave 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Debian 4.9.2-10) 4.9.2" 
    .section .note.GNU-stack,"",@progbits 

2.cpp,没有优化

.file "2.cpp" 
    .section .rodata 
.LC0: 
    .string "%d\n" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    subq $16, %rsp 
    movl $3, -12(%rbp) 
    leaq -12(%rbp), %rax 
    movq %rax, -8(%rbp) 
    movq -8(%rbp), %rax 
    movl (%rax), %eax 
    movl %eax, %esi 
    movl $.LC0, %edi 
    movl $0, %eax 
    call printf 
    movl $0, %eax 
    leave 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Debian 4.9.2-10) 4.9.2" 
    .section .note.GNU-stack,"",@progbits 

1.cpp,具有优化

.file "1.cpp" 
    .section .rodata.str1.1,"aMS",@progbits,1 
.LC0: 
    .string "%d\n" 
    .section .text.unlikely,"ax",@progbits 
.LCOLDB1: 
    .section .text.startup,"ax",@progbits 
.LHOTB1: 
    .p2align 4,,15 
    .globl main 
    .type main, @function 
main: 
.LFB12: 
    .cfi_startproc 
    subq $8, %rsp 
    .cfi_def_cfa_offset 16 
    movl $3, %esi 
    movl $.LC0, %edi 
    xorl %eax, %eax 
    call printf 
    xorl %eax, %eax 
    addq $8, %rsp 
    .cfi_def_cfa_offset 8 
    ret 
    .cfi_endproc 
.LFE12: 
    .size main, .-main 
    .section .text.unlikely 
.LCOLDE1: 
    .section .text.startup 
.LHOTE1: 
    .ident "GCC: (Debian 4.9.2-10) 4.9.2" 
    .section .note.GNU-stack,"",@progbits 

2。CPP,与优化

.file "1.cpp" 
    .section .rodata.str1.1,"aMS",@progbits,1 
.LC0: 
    .string "%d\n" 
    .section .text.unlikely,"ax",@progbits 
.LCOLDB1: 
    .section .text.startup,"ax",@progbits 
.LHOTB1: 
    .p2align 4,,15 
    .globl main 
    .type main, @function 
main: 
.LFB12: 
    .cfi_startproc 
    subq $8, %rsp 
    .cfi_def_cfa_offset 16 
    movl $3, %esi 
    movl $.LC0, %edi 
    xorl %eax, %eax 
    call printf 
    xorl %eax, %eax 
    addq $8, %rsp 
    .cfi_def_cfa_offset 8 
    ret 
    .cfi_endproc 
.LFE12: 
    .size main, .-main 
    .section .text.unlikely 
.LCOLDE1: 
    .section .text.startup 
.LHOTE1: 
    .ident "GCC: (Debian 4.9.2-10) 4.9.2" 
    .section .note.GNU-stack,"",@progbits 

结论

没有运行成本,当谈到优化GCC输出。与clang一样(在版本3.4.2中测试):优化开始时,生成的汇编代码在两个程序中都是相同的。

相关问题