So i have a reasonable understanding of pointers but i was asked what the difference between these are:
void print(int* &pointer)
void print(int* pointer)
I'm still a student myself and im not 100%. Im sorry if this is basic but my googleing skills failed me. Is there anyway you can help me understand this concept a bit better. I haven't used c++ in a long time, and i am trying to help to tutor a student, and i am trying to solidify my conceptual knowledge for her.
The first passes the pointer by reference, the second by value.
If you use the first signature, you can modify both the memory the pointer points to, as well as which memory it points to.
For example:
void printR(int*& pointer) //by reference
{
*pointer = 5;
pointer = NULL;
}
void printV(int* pointer) //by value
{
*pointer = 3;
pointer = NULL;
}
int* x = new int(4);
int* y = x;
printV(x);
//the pointer is passed by value
//the pointer itself cannot be changed
//the value it points to is changed from 4 to 3
assert ( *x == 3 );
assert ( x != NULL );
printR(x);
//here, we pass it by reference
//the pointer is changed - now is NULL
//also the original value is changed, from 3 to 5
assert ( x == NULL ); // x is now NULL
assert ( *y = 5 ;)
The first passes the pointer by reference.
If you pass by reference the function can change the value of the passed argument.
void print(int* &pointer)
{
print(*i); // prints the value at i
move_next(i); // changes the value of i. i points to another int now
}
void f()
{
int* i = init_pointer();
while(i)
print(i); // prints the value of *i, and moves i to the next int.
}
Related
As a beginner C++ coder, I am losing my head around pointers. I have correctly understood many things (and used them to implement different structures), but this "particular" situation is making me lose my head since Saturday.
If I pass a pointer by value (int* pointer), I am able to edit what it points to, but not the pointer (since it's a copy). And this correctly works. I am okay with that.
// pass a pointer by value (creating a copy)
void editPointerValue(int* pointer)
{
int c = 200;
int *p = &c;
// has no effect. perfect!
pointer = p;
}
if I call this function in my main, and print the pointer, it will stay the same. perfect.
BUT if I call one of these functions BEFORE:
// pass pointer to the pointer (allows pointer editing)
void editPointer(int** pointer)
{
int a = 75;
int *p = &a;
*pointer = p;
}
// pass pointer as reference (allows pointer editing)
void editPointerReference(int*& pointer)
{
int b = 100;
int *p = &b;
pointer = p;
}
Then, my pass-by-value function is allowed to change the pointer too!
what I mean is:
int a = 0;
int pointer = &p;
// (doesn't do anything)
editPointerValue(pointer);
// (correct. prints 0)
cout << *pointer << endl;
// (pointer / sets 75)
editPointer(&pointer);
// (reference / sets 100)
editPointerReference(pointer);
// (by value / shouldn't set to 200. Like before)
editPointerValue(pointer);
cout << *pointer << endl;
// should print 100, instead it prints 200.
I surrender. I don't know why calling another function before, changes the next one's behavior.
Solved: I was invoking Undefined Behavior and it still compiled in weird ways. (with no warning whatsoever)
I have gotten stuck on modifying pointers of pointers. The problem is that I don't understand why my code works. What I am trying to do is modify where a pointer-to-pointer points to in a function. Then accessing that value in my main function. I tried quite a few attempts and this is the only way I got it to work.
#include <iostream>
using namespace std;
void changePP(int **ppint) {
int *n = new int;
*n = 9; //just a value for demonstration purposes
*ppint = n; //THE LINE IN QUESTION
delete n;
}
int main() {
int **ppint = NULL;
int *p = new int;
*p = 4; //another value for demonstrating
ppint = &p;
cout << **ppint << endl;
changePP(ppint);
cout << **ppint << endl;
}
So, the output is 4 and then a 9 on seperate lines. However, I am not sure about the line *ppint = n in the code. Why do I have to use the * to change where ppint points to in the changePP function but not in the main? Also why do I not have to use the & in the function? I can't seem to find an explanation that I can understand on the internet and I was wondering if someone could explain this for me?
Note: these memory addresses are only for illustration.
Memory Layout
0x0A | 4
0x0B | 'p' -> 0x0A // Pointer to the value 4 in location 0x0A
0x0C | 'ppint' -> NULL // Initially a null pointer
Performing ppint = &p; produces the following because here ppint is the pointer located at 0x0C.
0x0A | 4
0x0B | 'p' -> 0x0A
0x0C | 'ppint' -> 0x0B
As for the parameter in the changePP function, I will refer to it as ppintCopy for less confusion. It's a copy (i.e., a pointer different than ppint) and modifying it only modifies the copy.
0x0D | 'ppintCopy' -> 0x0C // A pointer that points to `ppint`
Performing ppintCopy = &n would modify the pointer at 0x0D which is not the location of the pointer from the main function. However, deferencing ppintCopy (i.e., *ppintCopy) yields 0X0C which is the pointer from the main function therefore *ppintCopy = n; is changing where the pointer 0x0C points.
Why do I have to use the * to change where ppint points to in the changePP function but not in the main?
With the above illustration I hope it is more clear why it works in main and why you have to use a different syntax in the changePP function.
Also why do I not have to use the & in the function?
In the main function the variable ppint is of type int** (i.e., a pointer to a pointer) and p is of type int*. You cannot perform ppint = p; because the they are different types. This may be easier to see if you remove one level of indirection. For example:
int* pMyInt = NULL;
int myInt = 3;
I think it's pretty self explanatory that this cannot work (i.e., they are different types).
pMyInt = myInt;
However you can take the address of myInt using the & operator which results in a pointer to int (i.e., int*) and since this type is the same as the type of pMyInt the assignment is now possible.
pMyInt = &myInt;
ppint; // the variable name
*ppint; // dereference the first layer of pointer
*(*ppint); // dereference the first layer of pointer which points to another pointer that contains a **value**
Thus *ppint = n; means point ppint to another memory location which is the location assigned to n or it could be rewritten as *ppint = &n;
After that line, you have deleted the n but you didn't change its value so the value remains unchanged unless something have accessed and modified it.
The reason why you still retain the value of n after deleting it is considered as undefined behaviour though.
Pointers are already messy to deal with, you didn't have to make it worse. This works as well:
#include <iostream>
using namespace std;
void changePP(int *ppint) {
*ppint = 9;
}
int main() {
int p = 4;
int *ppint = &p;
cout << *ppint << endl; // this could be replaced with /*p*/
changePP(ppint); // note you could have replaced this parameter with /*&p*/
cout << *ppint << endl; // this could be replaced with /*p*/
}
Let me try to explain what your code is doing, but please for future, don't ever do it this way. Do it the way I've shown
#include <iostream>
using namespace std;
void changePP(int **ppint) {
int *n = new int; // you allocate memory for a single integer (again it is uninitialised)
*n = 9; // the value at the above pointer is now changed to 9
*ppint = n; // here you have just dereferenced a pointer to pointer which gives you a pointer, so in essence you are changing the location in memory where this pointer is pointing and it is now pointing to whatever memory address n was
delete n;
}
int main() {
int **ppint = NULL; // Here you have declared a pointer to pointer which is NULL
int *p = new int; // You can do better here with /*new int(4)*/
*p = 4; // this changes the value that p initially held (which could be anything)
ppint = &p; // reference to a pointer always creates a pointer to a pointer and since that is what ppint is, you are safe here
cout << **ppint << endl; // print the value nested within this pointer
changePP(ppint); // now you call the function with a variable of type pointer to pointer. Note you could have passed &p as parameter here and it would have still worked
cout << **ppint << endl;
}
What is the moral of the story?
When passing a parameter v to a function,
&v will produce a pointer to v
*v will dereference v and will give you access to whatever v was pointing to
When v is a parameter in a function,
&v will bring the actual object v into the scope of the function. This is called pass by reference
*v Is a pointer to v, and this is still pass by reference called pass by value because you are passing a pointer(Thanks Kirk)
A very general question: I was wondering why we use pointer to pointer?
A pointer to pointer will hold the address of a pointer which in turn will point to another pointer. But, this could be achieved even by using a single pointer.
Consider the following example:
{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b; //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b; //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}
I think you answered your own question, the code is correct, what you commented isn't.
int number = 10; is the value
int *pointer1 = b; points to the address where int number is kept
int **pointer2 = &b; points to the address where address of int number is kept
Do you see the pattern here??
address = * (single indirection)
address of address = ** (double indirection)
The following expressions are true:
*pointer2 == b
**pointer2 == 10
The following is not!
*pointer2 == 10
Pointer to pointer can be useful when you want to change to what a pointer points to outside of a function. For example
void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl; // writes 1337 to console
delete p;
}
A stupid example to show what can be achieved :) With just a pointer this can not be done.
First of all, a pointer doesn't point to a value. It point to a memory location (that is it contains a memory address) which in turn contains a value. So when you write
pointer1 = b;
pointer1 points to the same memory location as b which is the variable number. Now after that is you execute
pointer2 = &b;
Then pointer2 point to the memory location of b which doesn't contains 10 but the address of the variable number
Your assumption is incorrect. pointer2 does not point to the value 10, but to the (address of the) pointer b. Dereferencing pointer2 with the * operator produces an int *, not an int.
You need pointers to pointers for the same reasons you need pointers in the first place: to implement pass-by-reference parameters in function calls, to effect sharing of data between data structures, and so on.
In c such construction made sense, with bigger data structures. The OOP in C, because of lack of possibility to implement methods withing structures, the methods had c++ this parameter passed explicitly. Also some structures were defined by a pointer to one specially selected element, which was held in the scope global to the methods.
So when you wanted to pass whole stucture, E.g. a tree, and needed to change the root, or 1st element of a list, you passes a pointer-to-a-pointer to this special root/head element, so you could change it.
Note: This is c-style implementation using c++ syntax for convienience.
void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}
In c++ there is reference mechanismm and you generally you can implement nearly anything with it. It basically makes usage of pointers at all obsolete it c++, at least in many, many cases. You also design objects and work on them, and everything is hidden under the hood those two.
There was also a nice question lately "Why do we use pointers in c++?" or something like that.
A simple example is an implementation of a matrix (it's an example, it's not the best way to implement matrices in C++).
int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;
You'll rarely see this construct in normal C++ code, since C++ has references. It's useful in C for "passing by reference:"
int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}
The equivalent C++ code would use void *&p for the parameter.
Still, you could imagine e.g. a resource monitor like this:
struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}
Yes, it's contrived, but the idea's there - it will keep a pointer to the pointer stored in a holder, and correctly return that resource even when the holder's res pointer changes.
Of course, it's a dangling dereference waiting to happen - normally, you'd avoid code like this.
This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 8 years ago.
so right now i am trying to do some nift code for a little game i am making and I've run into something that has been bothering me for a while about pointers.
but first things first, i am trying to have a function take in a void* and give that void* a value, but it seems to not actually stay beyond the function like i'm used to. so...
void ItemGen(void* Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
Holder = NewItem;
}
it's not actually making "items" but various kinds of items that inherit from a item, this is just me making it simpler.
Holder gets changed but never make it outside the function, how should i change this, so that it does.
on top of that, i am sort of confused about a certain occurrence that can happen and i just want to know what happens when you do these. or really the difference between them
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
oh and is there a way to do a XOR operation on pointers so i can swap them with out a holding pointer.
i feel like i asked very stupid questions, but are confusing simply because they're void *'s.
Pointers are variables like any other, and as such are passed by value to functions. You've simply assigned a new value to the parameter copy of your pointer.
If you want to change a variable you pass to a function you must pass by reference or by pointer. Preferably the former.
void ItemGen(void *& Holder);
BTW, that's a horrible naming convention.
I am answering this point "Holder gets changed but never make it outside the function, how should i change this, so that it does."
void ItemGen(Item** Holder){
Item* NewItem
NewItem = new Item*
NewItem->Init();
*Holder = NewItem;
}
void someotherfunc() {
Holder * holder=0;
ItemGen(&holder)
if(holder!=0) {
holder->dosomething()
}
}
"void" simply means "nothing". A "void*" pointer points to nothing in particular. It's a way of saying "I don't know what kind of thing this pointer points to"; a void* pointer is a catch all that can receive any kind of pointer, but if you want to go from a void* pointer to any other kind, you have to explicitly cast it.
As to your first problem:
If you lived at "1234 Pointer Street", there is nothing magical about the number "1234", it's just a number. It only tells you anything when you treat it as a "pointer" - a house number. It "points" to a house on a particular street.
In the case of a computer, the street is memory.
int a = 0;
int* b = 0;
the variables "a" and "b" both contain the numeric value "0".
b = b + 1;
See? perfectly valid. So
void foo(int a, int* b)
{
a = a + 1;
b = b + 1;
}
void bar()
{
int x = 0;
int* y = 0;
foo(x, y);
// 'x' and 'y' are still zero here, they have to be, or you couldn't do
foo(0, 0);
}
Pointers to have some distinguishing features from regular variables.
int a = 0;
int* b = 0;
a = a + 1; // now a = 1
b = b + 1; // now b = b + sizeof(int) => 4.
What pointers do best is provide values for C/C++'s "dereference" operators.
a = *(b);
Going back to the streets example, if we assigned b our "1234 Pointer Street" address, it would be:
b = 1234;
What if we wanted to deliver something there?
*b
This means: The contents of the address that b describes.
Lets go back to the definition
int* b;
This says: "b is the address of an integer". How do we get the address of a specific integer?
// imagine a set of mailboxes.
int box1, box2, box3, box4, box5;
// lets put something interesting into box 3.
box3 = 5;
// now let's address somethign to box3.
// "&" is the "address of" operator.
int* pointer = &box3;
// now lets put something more interesting in pointer.
pointer = 10;
// whoops - that was wrong, we just changed the ADDRESS to some random numeric value.
// what we mean't was:
*pointer = 10;
printf("box 3 contains %d\n", box3);
// answer? 10, not 5.
After setting "pointer = &box3" we populated "pointer" with the location of box3's storage in memory, so when we wrote to that address using "*pointer = 10" we wrote to the storage address of box3.
You asked about
void *p1;
void *p2;
&p1 = &p2;
p1 = p2;
*p1 = *p2;
"&p1 = &p2" says "the address of p1 is the address of p2" and isn't legal, it wouldn't compile.
"p1 = p2" is legal, but it says "assign the same address as p2 to p1"
"*p1 = *p2" is illegal because you are using void pointers, which point to void, besides, you've just made p1 and p2 be equal to each other so it would be a null operation.
To fix your initial problem, you would need to provide a way for the caller to receive the new value you are creating.
Option 1: Accept a pointer-to-pointer
This is the very old-school C way to do it, but your code doesn't look very C++ so far so I'll list it first.
void ItemGen(void** Holder)
{
Item* NewItem = new Item;
NewItem->Init(); // why doesn't the constructor do this?
// ** means pointer to storage that is itself also a pointer,
// so if we dereference it once we will be refering to the inner pointer.
*Holder = NewItem;
}
Option 2: Return a pointer
void* ItemGen() // Why isn't this "Item*"?
{
Item* NewItem = new Item;
NewItem->Init();
return NewItem;
}
Option 3: Take a reference
void ItemGen(Item*& Holder)
{
Holder = new Item;
Holder->Init();
}
This says "Holder is a reference to a pointer to storage of type Item". It's exactly like a "Item*" pointer except instead of creating a temporary local copy of the value passed in, it's an alias for the value that was passed in.
If you absolutely have to throw away the type information of your pointer:
void ItemGen(void*& Holder)
{
Item* NewItem = new Item;
NewItem->Init();
Holder = NewItem;
}
At the level you appear to be with C++ so far, I would guess that your use of void* pointers is probably misguided.
Can someone please help me understand Reference and Dereference Operators?
Here is what I read/understand so far:
int myNum = 30;
int a = &myNum; // a equals the address where myNum is storing 30,
int *a = &myNum; // *a equals the value of myNum.
When I saw the code below I was confused:
void myFunc(int &c) // Don't understand this. shouldn't this be int *c?
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum);
cout<< myNum ;
}
int &c has the address to what's being passed in right? It's not the value of what's being passed in.
So when I do c+=10 it's going to add 10 to the memory address and not the value 30. Is that correct?
BUT... when I run this...of course with all the correct includes and stuff...it works. it prints 40.
Actually the ampersand in the function parameter list for myFunc is not an address operator, nor a bitwise and operator. It is a reference indicator. It means that within myFunc, the parameter c will be an alias of whatever argument is passed to it.
You have a few issues here.
your second line of code int a = &myNum; // a equals the address where myNum is storing 30 is wrong;
you can combine it with line 3 like so:
int *a = &myNum; // a equals the address where myNum is stored;
*a == myNum.
The type int & is read as "reference-to-int". Perhaps the Wikipedia article can help you understand what this means.
Both pieces of code are valid and your understanding of pointers in the first piece of code is correct. However, the ampersand (&) in the two pieces of code are actually different things. (Like how * is both the dereference and multiplication operator)
The second piece of code shows how the & can be used to pass variables to a function by reference. Normally if you had code like this:
int a;
void foo(int bar) {
bar = 3;
}
int main() {
a = 5;
foo(a);
// a still equals 5
}
The call to 'foo()' does not affect the variable you passed to it (bar or in this case, a). However if you changed this line:
void foo(int bar) {
to
void foo(int &bar) {
then it would affect the variable and at the end of the program above, the value of a would be 3.
In C++ when you pass things by reference using int &c you don't need to dereference. You only need to dereference pointers. If it was int *c then it would be necessary. Just remember in both cases you change the value of what was passed in the original caller so myNum is now 40.
Let's have a look at the assumptions first:
int myNum = 30;
// this won't compile. &myNum is the address of an int (an int *), not an int:
int a = &myNum;
// *a is a pointer to an int. It received the address of myNum (which is &myNum),
// and not its value
int *a = &myNum;
About the code:
void myFunc(int &c)
// c is passed by reference. This is a kind of "hidden pointer" that
// allows using the variable as if it was not a pointer but the pointed variable.
// But as this reference and the variable that was passed by the caller (myNum
// in your example) share the same address (this is the property of a reference),
// any modification of the value of c inside myFunc modifies it in the
// caller's scope too (so here, it modifies myNum).
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum); // displays 40
// What follows displays 40 as well, due to the fact
// c was passed by reference to myFunc that added 10 to it
cout<< myNum ;
}
So when I do c+=10 it's going to add 10 to the memory address and not
the value 30. Is that correct?
No, 10 was added to the value of c by myFunc.
As c is a reference (a "hidden pointer to") that received myNum, myNum was modified as well.