参考可能比指针更有效吗?

时间:2011-05-29 10:48:49

标签: c++ performance

我想知道有时(取决于平台或编译器或代码中的上下文等)引用是否比指针更有效?

6 个答案:

答案 0 :(得分:10)

  

参考是否比指针更有效?

Nopes!不必要。标准也没有这么说。

大多数编译器通过使用指针实现引用机制。参考文献被添加到C ++中以支持运算符重载而不是效率。

答案 1 :(得分:8)

是的,可能。我们可以说“它不能”的唯一方法是,如果标准中有一个要求(显式或暗示),则引用在所有情况下都比等效指针慢或慢。没有这样的要求,因为标准并不涉及这种性能细节。

例如,在低优化级别下,这是合理的:

int n = 0;
int *np = &n;
for (int i = 0; i < 10000000; ++i) {
    *np += i;
}
std::cout << n;

比这慢一点:

int n = 0;
int &nr = n;
for (int i = 0; i < 10000000; ++i) {
    nr += i;
}
std::cout << n;

只是因为在第一种情况下,编译器检测到它可以完全避免间接使用时更容易一些 - nr显然是n的别名,它在范围内,而*np 1}}恰好保留n的别名,因为我们在初始化之后永远不会分配给np。优化程度低的结果可能是指针情况下的间接性更强,循环效率更低。

看看你的编译器发出的代码,但是 - 没有优化的gcc为我发出了相同的代码,它看起来在两种情况下都发现了别名,并且使用了一个寄存器来表示总和和一个堆栈插槽{的{1}}。

当然,你期望一个好的优化编译器能够“理解”两种情况下的别名,并发出将i存储在寄存器中的代码,并且只接触循环中的寄存器(而不是内存)。

答案 2 :(得分:5)

您可以将NULL传递给指针,因此您必须检查指针变量是否为NULL。这是引用效率更高的唯一原因。

除此之外,编译器正在将引用实现为指针。

答案 3 :(得分:4)

除了直接访问外,没有什么比指针更有效。但速度并不是参考存在的原因。

答案 4 :(得分:4)

是的,引用可以比指针更有效。原因在于优化者。通常,现代CPU中最昂贵的操作之一是来自内存的负载。在调用(非内联)函数之后,编译器必须假设可以更改的内存中的任何变量都会发生变化。这意味着在以下示例中,必须在调用p后重新加载Bar()

class Foo {
  int* p;
  void Bar(); // defined somewhere else, not visible to compiler.
public:
  Foo() { p = new int; Bar(); std::cout << *p; }
};

现在,问题不在于*p必须重新加载,而是必须重新加载p。它也有机会。现在看下面的代码:

class Foo {
  int* p; // !
  void Bar(); // defined somewhere else, not visible to compiler.
public:
  Foo() { p = new int; int& r = *p; Bar(); std::cout << r; }
};

现在,编译器发现在p之后没有使用Bar()r是,它可能是作为指针实现的。但它无法重新分配!因此,优化器具有 在函数调用中保存r的选项。

答案 5 :(得分:3)

C ++引用的工作方式类似于“永久取消引用”指针。我希望性能是一样的。但是,由于无法重新分配引用的指针,编译器可能能够应用更多不能用于原始指针的优化。