13

In the example code below I allocate some instances of the struct Chunk. In the for loops I then iterate through the memory block and access the different instances by using either pointer or references, and assign them some random data.

But which for loop will execute the fastest? By my knowledge I'd say the reference-loop will be the fastest because it will require no dereferencing and has direct access to the instance in memory. How wrong / right am I?

struct Chunk {
    unsigned int a;
    float b;
    const char* c;
};

int main() {
    Chunk* pData = new Chunk[8];

    for( unsigned int i = 0; i < 8; ++i ) {
        Chunk* p = &pData[i];
        p->a = 1;
        p->b = 1.0f;
        p->c = "POINTERS";
    }

    for( unsigned int i = 0; i < 8; ++i ) {
        Chunk& r = pData[i];
        r.a = 1;
        r.b = 1.0f;
        r.c = "REFERENCES";
    }

    delete [] pData;
    return 0;
}
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
Michael Mancilla
  • 145
  • 1
  • 2
  • 8
  • 7
    Depends on your compiler I guess, but with mine they compile to the exact same code. Most C++ developers prefer references as a matter of style. – James M Sep 13 '12 at 14:10
  • Remember that a reference is like an automatically de-referenced pointer. – tadman Sep 13 '12 at 14:19
  • @tadman Not according to the standard. – James Kanze Sep 13 '12 at 14:38
  • There's a lot of technical detail as to why they're not identical, sure, but in general terms that's how they tend to behave. [The differences](http://en.wikipedia.org/wiki/Reference_\(C%2B%2B\)#Relationship_to_pointers) are important, but in this example aren't relevant. – tadman Sep 13 '12 at 15:22

5 Answers5

15

They should be the same (not about the same, but exactly the same) with any non-idiotic compiler. Under the hood, references are pointers (on 99% of compilers). There's no reason for any difference.

Pedantic: the second loop could be faster (probably not) because the data is in the cache already, but that's it. :)

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Probably a C fanatic who likes arrows better than ampersands. – tadman Sep 13 '12 at 14:18
  • 2
    Not 100% correct. References aren't pointers, they aren't objects at all. They could be implemented by pointers in several cases, but not 100%. And the code generated for pointer and for reference could differ. – Rost Sep 13 '12 at 14:18
  • Didn't downvoted, just recalled my upvote after read entire answer ;-) – Rost Sep 13 '12 at 14:20
  • @Rost on most compilers they are implemented with pointers (but I corrected the answer to reflect that it's not mandatory). Still, can you name one compiler where this doesn't hold? – Luchian Grigore Sep 13 '12 at 14:22
  • 1
    @LuchianGrigore Yes if you mean pointer is "memory address", no if (I mean) pointer is "object containing memory address". – Rost Sep 13 '12 at 14:27
  • 10
    I did not downvote, although I am inclined to do so: *references **are** pointers* is false. References **are** aliases, and can or cannot be pointers. The semantics are different, and the standard treats them differently. In particular in the code above, the compiler will most probably not even reserve space in the stack for the reference and just replace the reference with the referenced object. 8.3.2/4 *It is unspecified whether or not a reference requires storage (3.7).* That is **not** the behavior of a pointer. – David Rodríguez - dribeas Sep 13 '12 at 14:32
  • 2
    @LuchianGrigore Whether a compiler will implement the reference with a pointer or not will depend on a lot of things; most compilers will use pointers in some contexts, but not in others. Of course, the same thing is true even if you use a pointer; the compiler could easily suppress the pointer as well, _if_ it could prove that the pointer was never reseated. – James Kanze Sep 13 '12 at 14:32
  • Note that it is not just the percentage of compilers, but the specific use of the reference. A reference stored as a member of an object must have storage, but the reference in the question need not take space at all. – David Rodríguez - dribeas Sep 13 '12 at 14:33
  • @DavidRodríguez-dribeas you missed the "under the hood" part, which is important. – Luchian Grigore Sep 13 '12 at 14:33
  • @LuchianGrigore: We probably have a race condition here... read my last comment. *Under the hood* a reference may or not be a pointer, it depends on things like the lifetime of the reference and the scope. Two references in the same program may be implemented under the hood as just an alias (no space) or a pointer. – David Rodríguez - dribeas Sep 13 '12 at 14:35
  • 3
    @DavidRodríguez-dribeas Yes and no. The as-if rule will allow the compiler to do pretty much the same thing with pointers as it does with references, _provided_ it can prove that they meet the same conditions. The difference is that the compiler knows, without any analysis, that the reference won't be reseated, can't have its address taken, etc. In simple code like the above, this probably makes no difference, but in more complicated instances, using references instead of pointers can help the compiler. – James Kanze Sep 13 '12 at 14:35
  • 1
    @LuchianGrigore Actually, your second paragraph is almost certainly true. The second loop will be faster, because the data is already in the cache. On simple code like the above, it could easily be two or three times faster. – James Kanze Sep 13 '12 at 14:37
  • @JamesKanze well... as-if... the compiler might re-arrange the code (or not generate any code at all). – Luchian Grigore Sep 13 '12 at 14:39
  • 2
    @LuchianGrigore Good point. Any decent compiler will suppress both loops completely, since the state changes in them have no effect on the program output. With regards to your discussion with David, however: the standard says that references are _not_ objects, which makes them quite different from pointers. Theoretically. In practice, I don't think you can tell the difference between a reference and a pointer which is automatically dereferenced everywhere but in initialization: a reference behaves as-if it were an automatically dereferenced pointer. – James Kanze Sep 13 '12 at 14:46
  • @JamesKanze well, that's what I meant. You can't really answer stuff like this with theory. – Luchian Grigore Sep 13 '12 at 14:49
2

I'm tempted to say: who cares? Any difference in speed will be negligible, and you should chose the most readable. In this particular case, I would expect to see exactly the same code generated in both case. In more complicated cases, the compiler may not be able to determine later in the loop that the pointer has not been reseated, and may have to reread it. But for this to be the case, you'd have to be doing enough other things that the difference wouldn't be measurable.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Thank you for answering. This is, as you might notice, not a real world example. I'm just wondering what I should choose in a more complex scenario. – Michael Mancilla Sep 13 '12 at 14:45
  • @MichaelMancilla Whichever expresses best what you want to do. Generally, reference when possible, and pointer otherwise. Using reference tells the reader (and the compiler) that the referred to object will not change. – James Kanze Sep 13 '12 at 19:08
  • 3
    "Any difference in speed will be negligible," Your use case is not someones elses. – easytiger Jun 07 '16 at 12:22
1

There should be no difference in code produced by any decent compiler.

piokuc
  • 25,594
  • 11
  • 72
  • 102
1

When you hesitate between two versions of the code like those in your example, you should choose the one more readable. Possible optimization of the kind you propose is supposed to be done by the compiler.

The more readable in your case is rather the version with references (actually, maybe not really more readable, but the consensus is to prefer the usage of references because pointers are more "dangerous").

But back to the effeciency: (please if someone knows assembler, better stop reading or you risk a laugh attack...) In my opinion, as the pData is alocated on the heap, the compiler will have to compile it using pointers anyway. I think that your reasoning could be kind of correct if your structure was allocated on the stack just with "Chunk data[8];". But at latest when the compiler optimizations are on the difference should be deleted anyway.

David L.
  • 3,149
  • 2
  • 26
  • 28
  • On Linux, using g++ and clang++, the results of the above code are in fact the same, per compiler; I've determined this using `-S -O3` options on two separate .cpp files, and using assembly comments to keep track of things. For g++, I had to change the `8` to `100` so that it didn't unroll the `for` loop... For clang++, I had to `std::cout` the string to stop it from optimizing the `for` loop away... – Andrew May 27 '21 at 08:52
  • g++ did `leaq` `movq` `leaq` `movq`, and then in the loop, `movq`, `movl`, `movq`, `addq`, `movl`, `leaq`, `movl`, `cmpq`, `jne` – Andrew May 27 '21 at 08:56
  • clang++ did `movl`, and then in the loop, `movl`, `movl`, `movl`, `addl`, `jne`. For both g++ and clang++ each, the pointer and reference assembly output was indeed the same. – Andrew May 27 '21 at 08:57
1

The execution time is almost the same but using references in less hectic.

Keshav jha
  • 21
  • 5
  • Could you explain in more detail what you mean by "less hectic" and why the execution time would be almost the same? See [How do I write a good answer](https://stackoverflow.com/help/how-to-answer). – Jan Schultke May 24 '20 at 06:27
  • References are just syntactically better than pointers so that it is a little easy to understand and follow but pointers and references are pretty the much same thing as far as what the computer will actually do with them. references are not a variable unlike pointers, they are constants. and also reference only exist in our source code but the pointer is a variable and exists in memory. using references in place of pointers make the code less messy, so it is easier for me to debug it, so for me using references in place of pointers is less hectic. – Keshav jha May 25 '20 at 07:26