8

I'm wondering whether sometimes (depends on the platform or compiler or context in code etc) a reference can be more efficient than a pointer?

cpx
  • 17,009
  • 20
  • 87
  • 142
Guillaume Paris
  • 10,303
  • 14
  • 70
  • 145

6 Answers6

11

May a reference be more efficient than a pointer?

Nopes! Not necessarily. The Standard doesn't say that either.

Most compilers implement reference mechanism via use of pointers. References were added to C++ to support operator overloading and not for efficiency.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • interesting! could you explain why operator overloading with pointer can't work ? – Guillaume Paris May 29 '11 at 12:02
  • 1
    @Guillaume07 : Bjarne Stroustrup[A History of C++: 1979− 1991] said `References were introduced primarily to support operator overloading. C passes every function argument by value, and where passing an object by value would be inefficient or inappropriate the user can pass a pointer. This strategy doesn’t work where operator overloading is used. In that case, notational convenience is essential so that a user cannot be expected to insert address− of operators if the objects are large.` – Prasoon Saurav May 29 '11 at 12:06
  • 1
    @Prasoon: You should add this quotation in the answer itself. – Nawaz May 29 '11 at 12:54
  • Downvoter please explain your downvote. What's wrong with the answer? – Prasoon Saurav May 29 '11 at 13:13
  • I downvoted because what you say is true but not relevant to the question. The question is whether references may be faster, your "answer" is that references are not *designed* to be faster. But since the questioner has accepted your answer, perhaps I have somewhat misunderstood the question. If you add an explicit "yes" or "no" then I'll re-vote accordingly. – Steve Jessop May 29 '11 at 13:15
  • @Steve : I don't think the Standard mentions explicitly that using a reference would be better if efficiency is taken into consideration. It may be faster, it may be slower. The standard imposes no requirements. Most (All?) implementations use pointers to implement reference mechanism. So I can't think of a way how references would be faster than pointers. – Prasoon Saurav May 29 '11 at 13:25
  • The question says, "may a reference be faster". I don't see how either of us can possibly know enough about every implementation in existence to say, "no, it may *never* be faster". To say "it is not necessarily faster" is not at all the same as to say that "it is false to suggest that it may be faster". So I believe that the straight answer to the question must be "yes", although of course a discussion of whether that actually happens is useful. – Steve Jessop May 29 '11 at 13:27
  • 1
    @Steve : I didn't say "Yes" because I don't know which compilers implement reference mechanism without using pointers and how such an implementation is more efficient? – Prasoon Saurav May 29 '11 at 13:34
  • 1
    Ah. I didn't say "no" for exactly the same reason. – Steve Jessop May 29 '11 at 13:35
7

Yes, it may. The only way we could say "it can't" is if there were a requirement (explicit or implied) in the standard that references be as slow or slower than equivalent pointers in all cases. There is no such requirement, since the standard doesn't concern itself with that kind of performance detail.

For example, at low optimization levels it would be reasonable for this:

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

to be a little slower than this:

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

simply because it's a little easier in the first case for the compiler to detect that it can avoid the indirection entirely - nr is explicitly an alias for n everywhere it is in scope, whereas *np just so happens to remain an alias for n because we never assign to np after it is initialized. The result with low optimization might well be more indirection in the pointer case and a less efficient loop.

Take a look at the code your compiler emits, though - gcc with no optimization emits the same code for me, it looks to have spotted the alias in both cases and is using a register for the total and a stack slot for i.

Of course you'd expect a good optimizing compiler to "understand" the aliasing in both cases, and emit code that stores n in a register, and only touches that register (not memory) in the loop.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
6

You can pass NULL to the pointer, therefore you have to check if the pointer variable is NULL. That is the only reason why the reference is bit more efficient.

Other then that, compilers are implementing references as pointers.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
5

Yes, references can be more efficient than pointers. The reason lies in optimizers. In general, one of the most expensive operations in a modern CPU is a load from memory. And after you've called a (non-inlined) function, the compiler must assume that any variable in memory that could change, did change. That means that in the following example, it must reload p after calling Bar():

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

Now, the issue here is not that *p must be reloaded, but that p must be reloaded. It too could chance. Now look at the following code:

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; }
};

Now, the compiler sees that p isn't used after Bar(). r is, and it's probably implemented as a pointer. But it can't be reasssigned! Therefore, the optimizer has the option of saving r across the function call.

MSalters
  • 173,980
  • 10
  • 155
  • 350
4

C++ References work like "permanently dereferenced" pointers under the hood. I would expect the performance to be the same. However since a reference's pointee can't be reassigned the compiler might be able to apply more optimizations that can't be used for raw pointers.

seand
  • 5,168
  • 1
  • 24
  • 37
  • nice catch the optimizations. I somehow doubt it since the optimizer should be able to detect whether variables are modified or not (both gcc and Clang use SSA form in the intermediate representation for this). – Matthieu M. May 29 '11 at 11:10
  • @Matthieu: depends, there are cases where the compiler can't rule out that the pointer itself might be modified by some code that it calls out to and that has a pointer to the pointer. Since a reference can't be reseated, its referand is guaranteed still to be the same once the call returns, so in theory you'd win if (for example) its address was stored in a callee-saves register over the call. If the pointer value was stored in a callee-saves register then its value is stale after the call and has to be reloaded from the actual pointer object. In theory. – Steve Jessop May 29 '11 at 13:44
  • @Steve: The joys of escape analysis :/ – Matthieu M. May 29 '11 at 13:56
3

Nothing can be more efficient than a pointer, save for direct access. But speed is not why references exist.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358