Suppose that we have these two situations?
int p = 10;
int& q = p;
and
int p = 10;
int q = p;
Are not these two situations the same? I am little confused with the purpose of references, so please explain difference in these two.
int p = 10;
int& q = p;
In this case, q is for all practical purposes an alias for p. They share a memory location. If you modify q, you modify p. If you modify p, you modify q. q is just a different name for p.
int p = 10;
int q = p;
Here, q gets a copy of the value of p at the time when q is initialized. Afterwards, q and p are completely independent. Changing q does not affect p and changing p does not affect q.
In the second case, if you change the value of q it will not affect the value of p. In the first case, changing the value of q will also change the value of p and vice versa.
$ cat ref.cpp
#include <iostream>
int main () {
int p = 10;
int q = p;
int s = 10;
int& t = s;
q = 11;
t = 11;
std::cout << p << std::endl;
std::cout << q << std::endl;
std::cout << s << std::endl;
std::cout << t << std::endl;
s = 12;
std::cout << s << std::endl;
std::cout << t << std::endl;
}
$ g++ ref.cpp
$ ./a.out
10
11
11
11
12
12
$
In Second case p q are two independent integers. in first case both p q will point to same location in the memory. as you asked for the purpose of references. please go through call by value & call by reference. you can understand the use of references. go through the page. http://www.tutorialspoint.com/cplusplus/cpp_function_call_by_reference.htm
Changing a reference will change the underlying variable. This can be useful
in situations like:
int count_odd = 0;
int count_even = 0;
int i;
....
// Create a reference to either count_odd or count_even.
int& count = (i%1) ? count_odd : count_even;
// Now update the right count;
count++;
This is rather artificial, but it becomes more useful with rather more
complicated situations.
Related
When I implement the function, I originally define two variables 'p' and 'result' in one line.
void huffman(Node** nodeArray, int n)
{
int p,result = 0;
cout << p << endl;
sort(nodeArray, p, n); //sort
while(p < n-1){
Node* newNode = new Node;
newNode->fre = nodeArray[p]->fre + nodeArray[p+1]->fre;
p++;
result += newNode->fre;
nodeArray[p] = newNode;
sort(nodeArray, p, n);
}
cout << result << endl;
}
There are some bugs with the whole codes, so I add a line to test if 'p' is correct after defining. But the output is 1, which is wrong. Afterwards, I try to define two variables in two lines.
`
void huffman(Node** nodeArray, int n)
{
int p = 0;
int result = 0;
cout << p << endl;
sort(nodeArray, p, n); //sort
while(p < n-1){
Node* newNode = new Node;
newNode->fre = nodeArray[p]->fre + nodeArray[p+1]->fre;
p++;
result += newNode->fre;
nodeArray[p] = newNode;
sort(nodeArray, p, n);
}
cout << result << endl;
}
The output for 'p' is 0, which is correct. But I don't know why there is difference.
The line
int a, b = 0;
is equivalent to
int a;
int b = 0;
So, relative to
int a = 0;
int b = 0;
the difference is that a is not initialized.
In your specific code, since you have things like
while(p < n-1){
the execution is not determinable - p has not had an initial value set.
int p,result = 0;
It simply means that you have just declared a variable p, but you have declared and defined variable result. Some people also call it initialization (case of result).
Difference between declaration and definition of the variables:
Variable declaration refers to the part where a variable is first declared or introduced before its first use. Variable definition is the part where the variable is assigned a memory location and a value. Most of the times, variable declaration and definition are done together.
And now coming to you question i.e it doesn't matter if you declare two separate variables of same type in one line or not until you define them. It means It is not difference of line which giving you the different answer.
Now Let's take a look.
In first example when you write int p you just declared the variable. You not defined it or initialized it so you can't predict the value of p because it in this case it depends on the compiler. In most compilers it shows 0.
But In the second example you have defined the p and result both it means that p is showing the value 0 as per your intentions.
And the thing you saying that p is giving 1 as output..Are you sure that you are telling us value of p instead of result ?
you can do something like that:
int a,b;
a = b = 0;
the line
int a,b=0;
is just like
int a; int b = 0;
Ok so I am going to lay out two programs. Both are dynamic arrays using pointers and the new operator. But one doesn't seem to like the delete operator.
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
That's the first program. It likes the delete operator just fine. Now the program that dislikes the delete operator:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
This program compiles just fine. But during execution, it throws an error - free(): invalid pointer: 0xfdb038 .. or whatever the memory address is for that particular execution. So, the question is:
Why can't the delete operator be used in the second case?
I don't want to have memory leak; I don't want the pointer to be dangling.
If I just say p = NULL;, then p = 0, but I believe the pointer is still dangling?, but I'm not sure. Thanks in advance.
Look at this loop in the second piece of code:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
Notice that in this line, you write to the memory address currently pointed at by p. Since you always increment p and then write to it, you end up writing off past the end of the region that you allocated for p. (If we imagine pOrig as a pointer to where p initially points, then this writes to pOrig[1], pOrig[2], pOrig[3], pOrig[4], and pOrig[5], and that last write is past the end of the region). This results in undefined behavior, meaning that literally anything can happen. This is Bad News.
Additionally, delete[] assumes that you are passing in a pointer to the very first element of the array that you allocated. Since you've incremented p so many times in that loop, you're trying to delete[] a pointer that wasn't at the base of the allocated array, hence the issue.
To fix this, don't write to p after incrementing it, and store a pointer to the original array allocated with new[] so that you can free that rather than the modified pointer p.
You have to delete the pointer that you got from new. However, in your second code you did p++ which changed the pointer. Therefore you tried to delete a pointer you didn't get from new and delete crashes.
To fix this type of error never use new. Instead use std::vector<int> p;. Since you never need new you cannot forget a delete.
Problem is changing p in p++.
You should always store (to delete) original pointer. Like this:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}
From Java I'm used that I can do this:
public class SomeClass {
public int field1;
}
SomeClass[] data = new SomeClass[10];
for (int i = 0; i < 10; i++) {
data[i] = new SomeClass();
SomeClass d = data[i];
d.field1 = 10;
}
for (int i = 0; i < 10; i++) {
SomeClass d = data[i];
System.out.println("Value of data [" + i + "] is [" + d.field1 + "]");
}
And this will work fine, printing:
Value of data [0] is [10]
Value of data [1] is [10]
... etc
So in Java you first create the Array, which has by default all null values, and then in the first loop I create a new SomeClass and assign it to a slot in the array. If you don't do this you get a NullPointerException.
All fine.
The question:
I try to do the same in C++. I have one failing and one working example. But I am unsure why it works (or does not work, depending what example you pick). Can anyone elaborate?
First, the failing code:
int main(int argc, char **argv) {
MyClass data[10];
for (int y = 0; y < 10; y++) {
MyClass d = data[y];
cout << "INITIALLY (garbage): [" << d.field1 << ", " << d.field2 << "] " << endl;
// assign values
d.field1 = 2;
d.field2 = 3;
}
// print out data of first 10
cout << "Printing out data after initialization" << endl;
for (int y = 0; y < 10; y++) {
MyClass d = data[y];
cout << "[" << d.field1 << ", " << d.field2 << "] " << endl;
}
}
So If i understand correctly, according to this StackOverflow question I can create an array of a Struct like I do in the above code.
What I noticed is that if I do not use:
MyClass d = data[y];
d.field1 = 2;
d.field2 = 3;
But instead I do:
data[y].field1 = 2;
data[y].field2 = 3;
It does work.
However, if I insist on using a separate value, I can still make it work by doing this:
MyClass * d = &data[y];
d->field1 = 2;
d->field2 = 3;
I do not change anything in printing the output. And the above works.
So, something clearly is different when using a pointer to data[y]. I cannot found a clear answer on this though. Anyone able to explain why?
If this question is a duplicate, sorry for that, I could not find a real answer on the
"why" part. Code snippets are not always enough for me ;)
PPS: I am aware that I am not allocating this array in the heap. Bonus points for touching that subject to compare to :)
In C++, an object is a region of storage - that is, an area of memory. Variables denote objects directly, unless they are explicitly qualified as pointers or references to existing objects.
When you write:
MyClass d = data[y];
you are declaring a variable of type MyClass, defining it as denoting an object on the stack, and initialising it from the object data[y]; d and data[y] are separate objects so modifying d will not affect data[y].
You want to write:
MyClass &d = data[y];
^--- here
The ampersand & denotes d as a reference to the object data[y], so as long as an object continues to exist within the region of storage that data[y] originally denoted (i.e. at that address), you can use d to modify that object.
Using a pointer is similar, but because pointers can be reseated to point to a different object you must use indirection syntax (* or ->) to denote the object they point to.
This:
MyClass d = data[y];
d.field1 = 2;
d.field2 = 3;
Has no effect because d is now a copy of data[y]. If you said MyClass& d instead, you'd have a (non-const) reference, which you could modify and then observe those changes in data.
You are making a copy here:
MyClass d = data[y];
Modifications to d have no impact on data[y].
Take a reference instead:
MyClass& d = data[y];
Now d refers to the element data[y]. Note that in C++ a reference behaves like an alias. You cannot re-assign it. For example
d = someMyClassInstance;
will have the effect of assigning the value of someMyClassInstance to data[y].
int x = 4;
int* q = &x; // Is it always equivalent to int *q = &x; ?
cout << "q = " << q << endl; // output: q = 0xbfdded70
int i = *q; // A
int j = *(int*)q; // B, when is this necessary?
cout << "i = " << i << endl; // output: i = 4
cout << "j = " << j << endl; // output: j = 4
My question is what does lines A and B do, and why the outputs are both 4?
It is a basic usage of pointers, in A you dereference pointer (access the variable to which a pointer points)":
int i = *q; // A
while B is doing exactly the same but it additionally casts pointer to the same type. You could write it like that:
int j = *q; // B
there is no need for (int*)
int x = 4;
x is 4
int* q = &x;
q is the memory location of x (which holds 4)
cout << "q = " << q << endl; // output: q = 0xbfdded70
There's your memory location.
int i = *q; // A
i is the value at memory location q
int j = *(int*)q; // B
j is the value at memory location q. q is being cast to an int pointer, but that's what it already is.
int i = *q; // A
Dereferences a pointer to get the pointed value
int j = *(int*)q; // B
type casts the pointer to an int * and then dereferences it.
Both are same because the pointer is already pointing to an int. So typecasting to int * in second case is not needed at all.
Further derefenecing yields the pointed integer variable value in both cases.
Lines A and B are equivelent as q is already an int* and therefor (int*)q equals q.
int i = *q; yelds that i becomes the value of the integer pointed to by q. If you want to make i to be equal to the adress itself remove the asterisk.
A: Dereference - takes a pointer to a value (variable or object) and returns the value
B: Cast to int* and than dereference
The result is the same because the pointer is already to int. That's it.
Line A takes the value that q points to and assigns it to i. Line b casts q to the type int* (which is q's type already, so that cast is entirely redundant/pointless), then takes the value that q points to and assigns it to j.
Both give you 4 because that's the value that q points to.
Line A de-reference pointer q typed as int *, i.e. a pointer points to an int value.
Line B cast q as (int *) before de-reference, so line B is the same as int j = *q;.
I have int foo which has the address of an integer in it.
How do I add to the integer that foo is pointing to in one line?
Solution:
(*(int *)foo)+=1
This is how I handled it.
To add to the value the pointer is pointing to:
int * pointer;
int value;
(*pointer) += value; // parans for clarity, not necessarily needed
int a = 4;
int* foo = &a;
// and now the one line you asked
*foo = *foo + 2; // a = 6
If you are incrementing by one and feel like writing it the shortest way (++*pointer). Example:
int i = 0;
int* ip = &i;
cout << i << endl;
++*ip;
cout << i << endl;
Output:
0
1