引用和指针哪个更快?

7

据我所知,引用是变量的另一个名称,而指针则是自己的变量。指针占用空间。人们经常说“使用引用或指针”,但他们并没有说明哪个更好。如果引用不占用自己的内存,则在这方面引用胜出。我不知道编译器是否区分引用和普通变量。如果您对引用进行操作,它是否会编译为与普通变量相同的代码?


1
就性能而言,可能没有太大问题(在您的平台上运行一些测量来检查)。我认为更重要的是澄清您想要的语义 - 请记住,指针可以为NULL,因此可以说是可选的。 - Niall
3
参考文献就像是伪装成指针的东西,唯一的性能优势可以通过编译器对它们做出的一些额外假设来实现(它们不能合法地被重新指向,也不能为NULL)。 - Matteo Italia
相反地,即使指针参数被设计为可选,用户可能仍然害怕传递NULL指针。 - user2486888
3个回答

3

在内部,引用也是通过指针实现的。因此,很难说哪种更快,指针还是引用。

使用这两种方式的区别在于应用场景。

例如,您想将参数按引用传递给函数。

void func(int& a)    case_1
{
  //No need to check for NULL reference...
}
void func(int* a)    case_2
{
  //Need o check if pointer is not NULL
}

在case_2中,您需要在引用指针之前明确检查指针是否为NULL,而对于引用则不需要这样做,因为引用已初始化为某个值。
假设您以文明的方式玩游戏,即:
您不会像这样做:
int*p = NULL;
int &a = *p;

第一部分是绝对正确的。然而,在实践中,许多NULL检查是不必要的。只需在函数注释中记录您期望非NULL指针,并让空页崩溃程序,如果未满足该前提条件。 - cmaster - reinstate monica
在实践中,由于错误的指针访问,您会遇到许多分段错误。 - ravi
1
@cmaster:希望你能避免那些明确传递NULL的人,认为该参数是可选的。 - Matteo Italia

2

以下是我的两个测试程序:

参考资料:

int i = 0;
int& r = i;
++r;
int j = 0;
++j;

指针:

int i = 0;
int* r = &i;
++(*r);
int j = 0;
++j;

我的编译器为两者生成了完全相同的汇编代码。

movl    $0, -16(%rbp)   #, i
leaq    -16(%rbp), %rax #, tmp87
movq    %rax, -8(%rbp)  # tmp87, r
movq    -8(%rbp), %rax  # r, tmp88
movl    (%rax), %eax    # *r_1, D.31036
leal    1(%rax), %edx   #, D.31036
movq    -8(%rbp), %rax  # r, tmp89
movl    %edx, (%rax)    # D.31036, *r_1
movl    $0, -12(%rbp)   #, j
addl    $1, -12(%rbp)   #, j
movl    $0, %eax    #, D.31036

1
你能否使用像 -O3-O2 这样的优化标志转储汇编代码,然后再进行比较? - manav m-n
更好的转储使用-Os,它产生最易读的汇编代码。 - cmaster - reinstate monica
我不想这样做,因为它会优化整个代码,这并没有什么帮助。 - user4298783
1
所有从堆栈中来回跳转的内容似乎表明您使用禁用优化编译此代码,因此这并没有任何意义。如果您想要避免编译器将整个代码删除,请在最后将结果分配给一个“volatile”变量。 - Matteo Italia
@Matteo 对我没用。我把所有变量都设为易失性,但它仍然优化掉了所有内容。 - user4298783
1
使用一个全局的易失变量来存储结果,其他变量保持正常。另外,我通常会将每个情况放在一个函数中返回结果,并使用-c进行编译(除了-S -O3)。 - Matteo Italia

1
他们是相同的,引用只是一种语言机制,是一个不能为null的指针。不同之处仅在于编译阶段,在那里如果您尝试执行非法操作,将会收到投诉。

实际上,它们可以为NULL,尽管语言标准在创建NULL引用时称其为未定义行为。其效果与NULL指针相同。只是调试更难,因为许多人会认为引用不能为NULL,并因此不理解他们代码中正在发生的事情。 - cmaster - reinstate monica
它们可能是,但代码始终可以假设它们不是。 - mukunda
你可以对指针使用相同的假设,带来相同的后果。 - cmaster - reinstate monica
总会有奇怪的错误,但在一个工作设计中,引用始终是有效的,指针可能为空。 - mukunda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接