[openbeos] Re: Pointer or reference?

  • From: "anqe" <a_nqe@xxxxxxxxxxx>
  • To: <openbeos@xxxxxxxxxxxxx>
  • Date: Mon, 29 Mar 2004 01:02:32 +0100

> I'm not sure, what you mean by `code time constant', but passing something
> per reference means nothing else than that it is not passed by value. The
> `const' concept has nothing to do with this; a reference can refer to both
> constants and mutables.
>
> > Either way the 4B is still gonna be transferred somewhere along the
line,
> > via stack though the compiler nowadays might be passing it through in
> > fastcall.
> >
> > That &string is gonna make the compiler generate an "lea esi, string"
which
> > could possibly be avoided by using a constant pointer to the string. My
> > reasoning for this is that the compiler knows where it should be
> > initializing the variable and in some cases can make the assumption as
to
> > where it is, allowing the lea to be avoided.
> >
> > I could be off the mark, if so just ignore me (I try my best to ignore
me)
> > but it seems that if worrying about 4B of memory is an issue then there
are
> > probably other places to look for speed first. Condition hoisting and
> > appropriate usage of case and nested if structures would probably yield
more
> > performance than chassing all calls.
>
> Passing a reference to a function is not any different from passing a
pointer
> to it. In both cases the address of the referenced object must be passed.
>
> The following two functions, for instance, are compiled to exactly the
same
> executable code:
>
> extern "C"
> void
> add_one(int& var)
> {
> var++;
> }
>
> extern "C"
> void
> add_one(int* var)
> {
> (*var)++;
> }

Neither of those examples correspond to a code time constant. There is an
inherent difference when your dealing with constant pointers and references.

When the compiler passes a reference its sending a variable through without
being specific about what its going to be used for.

void echomsg (int& rString) {
    if (rString != 0) {
        printf(*rString);
    }
    else {
        printf("Echod null string");
    }
}

and say you called it as

// Some stuff now echo it to console
echomsg(*ErrorMessage);
// Where error message is a string defined when the code is written (hence
code constant)

that will make the compiler generate something along the lines of

// <- Somestuff
lea    eax, ErrorMessage
push eax
call    echomsg
-->
    enter    0,4    //I don't normally use enter so that might be a missuse
    pop    eax
    test    eax,eax
    jz        $steptoerror
    ...
    ...

and so on

Because your message has been defined at code time its not going to change
when the program runs, so this allows the compiler to make assumptions about
the data that it can't if you give it a reference.

void echomsg (const char* rString) {
       printf(rString);
}

will allow the lea to be eliminated and the compiled code can become

// <- Somestuff
push [ErrorMessage]        // !!! Different
call    echomsg                    // !!! Different
-->
    enter    0,4    //I don't normally use enter so that might be a missuse
    pop    eax


thats one instruction removed from the call and the push is now an rmw
instruction so it should pipeline better in the cpu. The other difference is
that the cleanup for a null pointer can be removed because the compiler
takes responisbility. Which isn't something it could do using reference, it
had to trust the programmer to never type echomsg(NULL) without pointer
cleanup. Whereas passing a NULL into the const char* version will most
likely cause the compiler to at least give a warning.

If the compiler were to inline the code then it could be simplified further.
Then again my example is hardly realistic since calling a function to simply
call printf is pretty much pointless.

bye, Scott

Other related posts: