-5

I need a once-and-for-all clarification on passing by value/pointer/reference.

If I have a variable such as

int SomeInt = 10;

And I want to pass it to a function like

void DoSomething(int Integer)
{
    Integer = 1;
}

In my current scenario when passing SomeInt to DoSomething() I want SomeInt's value to be updated based on whatever we do to it inside of DoSomething() as well as be most efficient on memory and performance so I'm not copying the variable around?. That being said which of the following prototypes would accomplish this task?

void DoSomething(int* Integer);
void DoSomething(int& Integer);

How would I actually pass the variable into the function? What is the difference between the previous two prototypes?

Finally if using a function within a class

class SomeClass
{
    int MyInteger;

public:
    void ChangeValue(int& NewValue)
    {
        MyInteger = NewValue;
    }
};

If I pass an integer into ChangeValue, when the integer I passed in get's deleted will that mean when I try to use MyInteger from within the class it will no longer be useable?

Thank you all for your time, I know this is kind of a basic question but the explanations I keep running into confuse me further.

KKlouzal
  • 732
  • 9
  • 32
  • Yes, those functions might accomplish the task. – Some programmer dude Jul 17 '14 at 09:07
  • 3
    -1 I'd be interested in a once-in-lifetime clarification how folks intend to learn a programming language as complex as C++ without looking at basic study material. – Solkar Jul 17 '14 at 09:24
  • You might be interested in reading the FAQ question http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c – Cecilia Jul 17 '14 at 09:36

4 Answers4

4

Both of your examples

void DoSomething(int* Integer);
void DoSomething(int& Integer);

will accomplish the task. In the first case - with pointer - you need to call the function with DoSomething(&SomeInt);, in the second case - with reference - simpler as DoSomething(SomeInt);

The recommended way is to use references whenever they are sufficient, and pointers only if they are necessary.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
  • Okay thank you very much, one last thing could you please see the class example in the question? – KKlouzal Jul 17 '14 at 09:27
  • @KKlouzal "If I pass an integer into ChangeValue, when the integer I passed in get's deleted will that mean when I try to use MyInteger from within the class it will no longer be useable?" - you cannot "delete" an integer. MyInteger just gets a new value, but is perfectly usable later. – Wojtek Surowka Jul 17 '14 at 09:28
4

Functionally, all three of these work:

  • pass an int and change the return type to int so you can return the new value, usage: x = f(x);

    • when you plan to set the value without needing to read the initial value, it's much better to use a function like int DoSomething(); so the caller can just say int x = f(); without having to create x on an earlier line and wondering/worrying whether it needs to be initialised to anything before the call.
  • pass an int& and set it inside the function, usage: int x; x = ? /* if an input */; f(x);

  • pass an int* and set the pointed-to int inside the function, usage: int x; x = ?; f(&x);

most efficient on memory and performance so I'm not copying the variable around

Given the C++ Standard doesn't dictate how references should be implemented by the compiler, it's a bit dubious trying to reason about their characteristics - if you care compile your code to assembly or machine code and see how it works out on your particular compiler (for specific compiler commandline options etc.). If you need a rule of thumb, assume that references have identical performance characteristics to pointers unless profiling or generated-code inspection suggests otherwise.

For an int you can expect the first version above to be no slower than the pointer version, and possibly be faster, because the int parameter can be passed and returned in a register without ever needing a memory address.

If/when/where the by-pointer version is inlined there's more chance that the potentially slow "needing a memory address so we can pass a pointer" / "having to dereference a pointer to access/update the value" aspect of the pass-by-pointer version can be optimised out (if you've asked the compiler to try), leaving both versions with identical performance....

Still, if you need to ask a question like this I can't imagine you're writing code where these are the important optimisation choices, so a better aim is to do what gives you the cleanest, most intuitive and robust usage for the client code... now - whether that's x = f(x); (where you might forget the leading x =), or f(x) where you might not realise x could be modified, or f(&x) (where some caller might think they can pass nullptr is a reasonable question in its own right, but separate from your performance concerns. FWIW, the C++ FAQ Lite recommends references over pointers for this kind of situation, but I personally reject its reasoning and conclusions - it all boils down to familiarity with either convention, and how often you need to pass const pointer values, or pointer values where nullptr is a valid sentinel, that could be confused with the you-may-modify-me implication hoped for in your scenario... that depends a lot on your coding style, libraries you use, problem domain etc..

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Thank you. I've been passing by pointer everywhere in my application however I've recently run into a slight performance drop and want to be 100% clear on pointers/references and how to avoid copying the variable during a function call at all costs. – KKlouzal Jul 17 '14 at 09:33
  • You're welcome. Passing by pointer or reference can be useful when you're passing large objects that are slow to copy, but given `int` is no larger and may be smaller than a pointer, it's not helpful for `int`. Do try a profiler (e.g. g++/VC++ have inbuilt ones, ValGrind etc) - that may turn up all sorts of unexpected things that will make a more dramatic difference. – Tony Delroy Jul 17 '14 at 09:38
0

You can use either. Function call for first prototype would be

DoSomething(&SomeInt);  

and for second prototype

DoSomething(SomeInt);  
haccks
  • 104,019
  • 25
  • 176
  • 264
0

As was already said before, you can use both. The advantage of the

void DoSomething(int* Integer)
{
  *Integer=0xDEADBEEF;
}
DoSomething(&myvariable);

pattern is that it becomes obvious from the call that myvariable is subject to change.

The advantage of the

void DoSomething(int& Integer)
{
  Integer=0xDEADBEEF;
}
DoSomething(myvariable);

pattern is that the code in DoSomething is a bit cleaner, DoSomething has a harder time to mess with memory in bad ways and that you might get better code out of it. Disadvantage is that it isn't immediately obvious from reading the call that myvariable might get changed.

Markus Dheus
  • 576
  • 2
  • 8