我想知道有时(取决于平台或编译器或代码中的上下文等)引用是否比指针更有效?
答案 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 ++引用的工作方式类似于“永久取消引用”指针。我希望性能是一样的。但是,由于无法重新分配引用的指针,编译器可能能够应用更多不能用于原始指针的优化。