Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we not pass POD by reference in functions?

Tags:

c++

I've always been told that we should not pass POD by reference. But recently I've discovered that a reference actually takes no memory at all.

So why do we choose to write:

void DoSomething(int iNumber);

instead of:

void DoSomething(const int& riNumber);

is it not more efficient?

like image 226
xcrypt Avatar asked Sep 26 '11 21:09

xcrypt


4 Answers

Actually in this case (using int) passing by value is probably more efficient, since only 1 memory-read is needed instead of 2, to access the passed value.

Example (optimized using -O2):

int gl = 0;

void f1(int i)
{
    gl = i + 1;
}

void f2(const int& r)
{
    gl = r + 1;
}

int main()
{
    f1(1);

    f2(1);
}

Asm

    .file   "main.cpp"
    .text
    .p2align 2,,3
.globl __Z2f1i
    .def    __Z2f1i;    .scl    2;  .type   32; .endef
__Z2f1i:
LFB0:
    pushl   %ebp
LCFI0:
    movl    %esp, %ebp
LCFI1:
    movl    8(%ebp), %eax
    incl    %eax
    movl    %eax, _gl
    leave
    ret
LFE0:
    .p2align 2,,3
.globl __Z2f2RKi
    .def    __Z2f2RKi;  .scl    2;  .type   32; .endef
__Z2f2RKi:
LFB1:
    pushl   %ebp
LCFI2:
    movl    %esp, %ebp
LCFI3:
    movl    8(%ebp), %eax
    movl    (%eax), %eax
    incl    %eax
    movl    %eax, _gl
    leave
    ret
LFE1:
    .def    ___main;    .scl    2;  .type   32; .endef
    .p2align 2,,3
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB2:
    pushl   %ebp
LCFI4:
    movl    %esp, %ebp
LCFI5:
    andl    $-16, %esp
LCFI6:
    call    ___main
    movl    $2, _gl
    xorl    %eax, %eax
    leave
    ret
LFE2:
.globl _gl
    .bss
    .align 4
_gl:
    .space 4
like image 80
6 revs Avatar answered Oct 03 '22 11:10

6 revs


Not passing PODs by reference seems like a too general rule. PODs can be huge, and passing references to it would be worth. In your particular case, an int is the same size than the pointer that most -if not all- implementations use in the background to actually implement references. There is no size difference between passing an int or a reference, but now you have the penalty of an extra level of indirection.

like image 31
K-ballo Avatar answered Oct 03 '22 13:10

K-ballo


Passing by reference is passing by pointer in disguise.

With small data, it can be faster to access it as values rather than having to deference the pointer several times.

like image 21
Pubby Avatar answered Oct 03 '22 11:10

Pubby


Because it is a meaningless efficiency gain 99.999% of time, and it changes the semantics. It also prevents you from passing in a constant value. For example:

void Foo(int &i) { }
Foo(1);  // ERROR!

This would work however:

void Foo(const int &i) { }
Foo(1);

Also, it means that the function can modify the value of i such that it is visible to the caller, which may well be a bad thing (but again, you could certainly take a const reference). It comes down to optimizing the parts of your program where it matters and making the semantics of the rest of the code as correct as possible.

a reference actually takes no memory at all.

Not sure who told you that, but it's not true.

like image 33
Ed S. Avatar answered Oct 03 '22 13:10

Ed S.