Demystify function parameters

Started by
5 comments, last by fpsgamer 16 years, 5 months ago
Ok so I've played around with C/C++ for about 10 years or so, written a few games, custom apps, etc. Despite my experience, I've had a question in my mind that I haven't been able to find a solid answer to. Basically, if I set up a function header to pass a class object or a structure, what actually happens? For instance:

void main() {

  myClass myObject;

  foo(myObject);
}

void foo(myClass argObject) { // code }
So from what I've read about passing parameters, this passes myObject by value. So if I'm understanding this correctly, argObject is a local class to function foo. If that is the case, does that mean that all of myObject's memory space is copied to argObject? The real question in my mind is what happens from a memory perspective? What is the difference between passing argObject like this:

void foo(myClass argObject) { // code }
this:

void foo(myClass * argObject) { // code }
or this:

void foo(myClass & argObject) { // code }
...from a memory perspective? Please share your insight on this...my understanding of function parameters has never been completely solid. Thanks!
Advertisement
The C++ standard doesn't specify what happens at the memory level, only what the observable side effects are.

However usually:
- in the pass by value case, you'll get a copy of the object
- the pass by pointer, pass by reference will be implemented identically under the hood, by passing the address of the object.

Exactly what happens will depend on your compiler and the calling convention used.
Quote:
So if I'm understanding this correctly, argObject is a local class to function foo.

Nope. argObject is simply a copy of whatever value was passed to the function. The class itself (myclass) is not locally-scoped to the function, otherwise it would not be possible to pass it as a parameter.

Quote:
If that is the case, does that mean that all of myObject's memory space is copied to argObject?

The copy constructor of myclass is invoked to construct a new myclass named argObject that is a copy of myObject. The definition of that constructor determines what exactly is copied (although the object will always be the same size and occupy the same amount of space on the stack).
Quote:Ok so I've played around with C/C++ for about 10 years or so,


How can you program for 10 years in a language, and not know the difference between passing by value and passing by reference? Just wondering, since it's a pretty crucial and fundamental concept for both, performance as well as code safety.

Quote:void foo(myClass argObject) { // code }


This creates a new object, and copies all the values in the object you passed into new instance. (sizeof(myClass) == ???). Changing argObject doesn't affect what was passed as parameter.

Quote:void foo(myClass * argObject) { // code }


Copies the value of pointer to myClass. (sizeof(myClass*) == 4 (32-bit))

Quote:void foo(myClass & argObject) { // code }


Copies the value of reference. Similar to pointer, with restrictions that apply to references. (sizeof(myClass&) == 4 (32-bit))

Later two examples modify the passed object directly - so whatever you pass as parameter, may get modified by the function. If first example, changes are discarded once function returns, unless myClass contains pointers or references to other objects.

Copying here refers to stack allocated objects, and the sizes as they are defined by your architecture. How the allocations will be performed exactly, and what is allocated will depend on calling convention. For passing by value, the object's members will always have the same layout though.

In reality, inlining will frequently be performed to reduce copying. Depending on the compiler, this may happen automatically, or when explicitly specified.

Const modifier may also affect what compilers considers to be safe to do, but cannot fully enforce it. Marking various parts of parameter as const will determine what you may or may not modify.

In that case, there might be no difference between how you pass the parameter.

For all the intricate details about various other issues and how things are done in practice, this covers it pretty well, but it's scattered over multiple articles.

Then there's also:
void foo(myClass * &argObject)
(I hope I got this right).

This should pass reference to pointer, meaning function may change the value of the parameter that was passed. If you pass x into such function, and function changes argObject's value to another pointer, x will change too.
Quote:Original post by Antheus
Quote:Ok so I've played around with C/C++ for about 10 years or so,


How can you program for 10 years in a language, and not know the difference between passing by value and passing by reference? Just wondering, since it's a pretty crucial and fundamental concept for both, performance as well as code safety.


Trust me, I know the difference. I have used both passing methods in several programs and they have worked just fine. Maybe I wasn't specific enough - I just wasn't sure of what exactly happens behind the scenes when passing class objects or other data structures. I understand that if I pass an object by value, a local copy is created and when the function ends the object is lost. What I didn't know, was that the passing object's copy constructor was called to create the copy. I assumed, but wasn't positive.

It's hard finding good reference material about something this specific as most tutorials cover basic function passing. Thanks for your comments!
Quote:Original post by PomPyro
Trust me, I know the difference.... I assumed, but wasn't positive.

It's hard finding good reference material about something this specific


The standard? Google? Testing it yourself (e.g. by setting a breakpoint within the copy constructor)?

(Also, part of "asking questions the smart way" when you have "assumed" something is to state your - qualified - assumptions up front; this prevents respondents from going into "assume utter cluelessness" mode.)
Quote:Original post by PomPyro
What I didn't know, was that the passing object's copy constructor was called to create the copy. I assumed, but wasn't positive.


Yes, when you pass an object by value it will be copied using the objects copy constructor. Where it will appear in memory is something that depends on 'function calling convensions' which is specific to particular processors/platforms. For example you may recall seeing some of these name preceding function declarations: pascal, cdecl, fastcall etc. These names describe how your arguments will be located in memory.

Quote:Original post by PomPyro
It's hard finding good reference material about something this specific as most tutorials cover basic function passing. Thanks for your comments!


Using tutorials may be your problem. I, and many others here generally find the internet to be a rubbish source of technical information. Bound, well reviewed books will provide most of the information you'll need.

This topic is closed to new replies.

Advertisement