0

I am working through a c++ book/guide, but the pointers and references seem a little vague to me. This is coming from myself as a C# programmer and c# mindset that uses

foo(ref int x) and bar(out int y)

A small piece of code I wrote to show the memory position and memory position value, but I do not fully understand what each means, and in what context this is in.

int main()
{
    int i = 50;
    foo(&i);
    cout << "\n\n" ;
    foo(i);
    getchar();
    return 0;
}

void foo(int& bar) // & refer
{
    cout << "refer";
    cout << "\n&bar = " << &bar;
    cout << "\nbar = " << bar;
}

void foo(int* bar)// * pointer
{
    cout << "prefer";
    cout << "\n&bar = " << &bar;
    cout << "\nbar = " << bar;
}

output shows:

pointer
&bar = 0018FC30
bar = 0018FD04

refer
&bar = 0018FD04
bar = 50

What does & and * in each case mean, and how does it affect the output?

ofcourse, I have added all necessary methods into the .h file

UPDATE AFTER READING SOME ANSWERS

int i (values from pointer, aka points directly to variable)

  • has a value = 50
  • has an memory address = 0018FD04

pointer which points to int i

  • has a value which is int i memory address = 0018FD04
  • has its own memory address = 0018FC30

thus, to clarify, using a "refer" or "&bar" in the example actually creates a new variable which duplicates the int i passed through in the foo(int& bar).

Instead of the new &bar value containing the 50, it will have the memory address of the int i.

TL;DR

  • foo(int bar) receives the "value" of the variable
  • foo(int* bar) receives the "value" of the variable, if changed, it will change the variable in the calling method.
  • foo(int& bar) receives the pointer/memory address of the variable.

I hope others find this as useful as I did, thank you all!

CybeX
  • 2,060
  • 3
  • 48
  • 115

5 Answers5

0

Coming from C#, pointers can be thought of like classes, while values act more like structs - when you alter their members, you're either altering a copy (in the case of pass-by-value objects, which is not shown), altering the same object you've been passed (in the case of pass-by-pointer), or altering the same value including the reference to the actual value you've been passed (in the case of pass-by-reference). In other words, instead of the object's declaration controlling how it's passed, the implementation decides how it's passed.

For each method header, behavior is as follows:

void foo(int& bar) // & refer

When you pass using type& name, you're passing by reference, and you're passing the equivalent of C#'s ref (or out if you didn't give the variable a meaningful value to begin with). Even though you've passed a value, changes to the value, including changing the value itself, will be reflected in the calling scope.

void foo(int* bar)// * pointer

When you pass an object using type* name, you're passing the pointer to that object. You are, however, passing the pointer as a value, so while you could change members (moot in the case of an int) you could not change the value (bar) itself. Again like C#, this would be like passing a class object without the use of ref/out - reassignment won't be reflected in the calling scope.

Going over the use of & in code...

cout << "\n&bar = " << &bar;

In this case, & the "address-of" operator. Whenever you take &variable in code, you're going to get the memory address of that variable - printing this value will give your the hexadecimal address the variable lives in RAM, which is basically gibberish in all but the most technical debug and sample cases. This also applies to pointers - you can take the pointer of a pointer (of a pointer of a pointer... ad infinitum).

David
  • 10,458
  • 1
  • 28
  • 40
0

Imagine we have:

int* a; // This holds memory addresses
a = new int;

cout << a; // This will print the memory address of your new int
cout << *a; // This will print the value at the memory address a is holding 
cout << &a; // This will print the memory address of the pointer variable.

If you declare a function that takes a pointer as a parameter, you should pass a pointer and not a static variable.

I hope this helped you even if its just a little bit.

Victor
  • 907
  • 2
  • 17
  • 42
  • 2
    I find this rather confusing, because `a` in your case is the pointer, and when you print `*a` you print the value `a` is pointing to, while `a` is just the value of `a` (aka the adress of the newed int) – 463035818_is_not_an_ai Jan 28 '16 at 15:10
  • 3
    ...and I also dont agree with "a pointer is a variable that points to a memory address". A pointer (may) point to some other object,when its value is the address of this other object. – 463035818_is_not_an_ai Jan 28 '16 at 15:13
  • @tobi303 true that, my definition was rather vague. I apologize for that. And yeah, pointers are confusing A.F. – Victor Jan 28 '16 at 15:39
  • you still say, `*a` would be the value of `a`. Putting it in capital letters does not make it less wrong. I still insist, that the value of `a` is `a`, while `*a` is the value after dereferencing `a`. – 463035818_is_not_an_ai Jan 28 '16 at 15:49
  • @tobi303 better? Feel free to edit the answer by yourself – Victor Jan 29 '16 at 06:40
0

Okay, the pointer first :

void foo(int* bar)// * pointer
{
    cout << "prefer";
    cout << "\n&bar = " << &bar;
    cout << "\nbar = " << bar;
}

You're calling it with

int i = 50;
foo(&i);

In this context, *bar will be 50 (get the value the int pointer is pointing to). &bar is the address of the pointer that is created ( the pointer itself needs a place in memory too of course ). bar is the address of the object the pointer is pointing to ( i in this case )

Reference case:

void foo(int& bar) // & refer
{
    cout << "refer";
    cout << "\n&bar = " << &bar;
    cout << "\nbar = " << bar;
}

Here, bar will refer to i that you created in main. &bar will return the address of i and bar it's value, 50 in this case. References themselves don't have their own addresses.

Community
  • 1
  • 1
Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
0

I am working through a c++ book/guide, but the pointers and references seem a little vague to me

You'll find plenty of explanations for this if you try searching, but here is my attempt.

A pointer is a variable that tells you where to find another variable, by pointing to it. A pointer is really just a number that corresponds to the address in memory of another variable. Examples of addresses are the 0018FC30 and 0018FD04 in your output.

A reference is an alias (another name for) a variable. If you have a variable a and you create a reference b to it, b becomes an alternative name for a. The value of a reference is not an address like for a pointer, it's the value of whatever it refers to. The interest of references is that when you copy them or pass them around, you're not copying the actual value (which can be expensive), you're only copying the name.

The main observable difference is that you can change what a pointer points to (by changing the value of a pointer, since its value is really just an address), but you can't change what a reference refers to (in a way, it becomes what it refers to).

What does & and * in each case mean, and how does it affect the output?

When you have a variable a, the expression &a means "take the address of a". This is interesting, because if you have the address of a variable, you can make a pointer point to it.

And *a could be seen as more or less the inverse operation, if you have a pointer a, *a means "take the value at the address this pointer points to".

You can use &a on anything that has an address. You could even take the address of a pointer to create a pointer-to-pointer! But you can only use *a on something that behaves like a pointer, it would be meaningless otherwise.

Community
  • 1
  • 1
tux3
  • 7,171
  • 6
  • 39
  • 51
0

In C++ the default is pass by value. So if you have a f(X x) then the compiler is going to generate code that copies the class X every time you call the function. If X is large (like an array, string, map or something like that) you probably don't want a copy, for performance reasons. Making a copy also means that if you modify the parameter inside your function you only modify the copy so it won't be visible after you return.

Now to make things visible outside of the function you must modify the instance of the caller. To do this you must have a pointer(*) or a reference(&) to that instance. The immediately visible difference between the two is that you can compare the pointer to nullptr (it's more tricky for the reference), that for the pointer you must use -> to access it's members, vs . for the reference and that when calling you must take the address of the argument to get the pointer (f(&global_x)). In general you should use references where there argument can never be nullptr. You should prefer pointer when it's reasonable to call the function with that argument missing. These are equivalent with C# ref or out. There are more subtle differences between the two but they only become apparent if you are writing templates and libraries.

If you want to avoid the copy but you don't want to modify the argument you should use const, which asks the compiler to make sure that you don't accidentally modify the value. You can use it with both references and pointers.

Picking references vs. pointers is most of the time a ting of coding style. The most important thing is to be consistent because it is annoying having to lookup function definitions all the time to see if you used pointers or references that one time.

Sorin
  • 11,863
  • 22
  • 26
  • References cannot be null, thus `most of the time a ting of coding style` really depends on what the method/function is supposed to do and if null is expected or not. Also, because of move semantics a copy is rarely performed. – Hatted Rooster Jan 28 '16 at 15:25
  • @JameyD `const X& x = *static_cast(nullptr)`. If you really want to, but please don't! You can still take a pointer, even if you don't expect a null if you think it helps in other ways (style). Move semantics help a lot, but it's very easy to mess it up and make it decay into a copy if you're not careful. If you pass a reference or a pointer it's guaranteed that no copy will ever happen. – Sorin Jan 29 '16 at 09:18