This question is regarding Function Stack Creation.
Suppose we create a function fn(int a,char b) and call from main fn(A,B) , in this case when the function is called a fn. stack is created with return address, Stack pointer (etc) where local variables and parameters are created and on return is destroyed.
I have a few questions:
1) For our parameterized constructor suppose
myClass{
int a;
char c;
public:
myClass(int a,char c)
{
this->a=a;
this->c=c;
}
};
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c.
2) Now suppose we are calling by reference : my function is fn(int* a,char* b) or fn(int& a, char& b) and calling from our main by fn(&A,&B) and fn(A,B) respectively , in this case also, a function stack will be created with return address,SP etc. My question is that, will a local pointer or reference be created on stack in this case (i.e. creating a local copy of pointer or reference that will point to the passed object). Or is it that no local copy of object is created and the original object pointed by the pointer or the refence is directly passed?
3) Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
Thanks
EDIT
#include <iostream>
using namespace std;
void fn(int , char);
//void fn (int* a, char* c);
void fn (int& a, char& c);
int main()
{
int a=10;
char c= 'c';
cout << "Inside main()" << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
fn(a,c);
//fn(&a,&c);
fn(a,c);
return 0;
}
void fn (int a, char c)
{
int tempInt;
char tempChar;
cout << "\n\nInside Call By Value Function " << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
cout << hex << "&tempInt : " << &tempInt << endl;
cout << hex << "&tempChar : " << (int *)&tempChar << endl;
}
/*void fn (int* a, char* c)
{
cout << "\n\nInside Call By Pointer Function " << endl;
cout << hex << "*a : " << a << endl;
cout << hex << "*c : " << (int*) c << endl;
}
*/
void fn (int& a, char& c)
{
cout << "\n\nInside Call By Reference Function " << endl;
cout << hex << "*a : " << &a << endl;
cout << hex << "*c : " << (int*) &c << endl;
}
Output:
$ make
g++ -Wall Trial.cpp -o Trial
Trial.cpp: In function `int main()':
Trial.cpp:19: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
Trial.cpp:21: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
make: *** [Trial] Error 1
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c
Yes, a function stack is created but a and c are not local variables to the function stack, they are member variables and there lifetime does not end with the end of the constructor. They remain alive throughout the lifetime of the class instance whose member they are.
Or is it that no local copy of object is created and the original object pointed by the pointer or the reference is directly passed?
This is known as pass by reference. The two ways are:
Passing the address of the object or
Pass the object by a reference
In either case the copy of the object is not created. The actual object can be modified within the function, In case 1 the pointer in the function points to the address of the object being passed while in case 2 the reference argument is merely an alias to the object being passed.
Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
No, you cannot because the compiler cannot understand which function version you intend to call when you call it as:
int i = 10;
int j = 20;
fn(i,j);
I misread, as fn(int& a,int& b) and fn(int a,int b) instead of fn(int& a,char& b) and fn(int a,int b).
Ofcourse you can. They have distinct types and hence qualify as valid overloaded functions.
To begin with, your concept is slightly incorrect.
i.e. Stack is not created with a function call. Rather each thread of execution has its own stack already. It is even there when a single main is called. However an ACTIVATION record is pushed on the stack when a function is called. And the same is popped when returning from a function.
So for
Stack is already there and an activation record is pushed on the stack for each function call. The variables live throughout the lifetime of the object.
If your function takes a pointer as argument (i.e. call by reference), there will be a pointer variable pushed on the stack which is passed the address of the original variable. The original variable remains intact and modifying its value via pointer would change the original variable.
You can only overload functions when their signatures are different. This means type, number or order of parameters. In the e.g. you quoted, it is not possible to differentiate whether a passed int is a variable or it is an address of a variable. Hence this overload won't work.
EDIT: Point 3 above has as slight mistake. The e.g. quoted in question has second parameter different and hence qualifies as valid overload. Note that the criteria is not just the name of data type (i.e. int vs. int * is also different types), but rather the fact that given an input value, compiler should be able to differentiate and chose which overloaded version to call.
Related
This question already has answers here:
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 4 years ago.
I know call by pointers in which we pass address of variables.Something like this:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);
And also call by reference,in both of these methods the changes made in the function are reflected in actual arguments' variable.
But why are actual parameters passed in this case of call not changed:
#include <iostream>
using namespace std;
void foo(int* c){
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout<<&c<<endl; //0x7ffe1a74f3b0
foo(c);
cout<<*c<<endl;//5
cout<<&c<<endl;//0x7ffe1a74f3b0
}
Here c passed to foo() is address of a.So how this is call by value.
Here c should have printed garbage value according to me.Please explain what has happened here.
And also call by reference, in both of these methods the changes made in the function are reflected in actual arguments' variable.
There is an important difference, though: the changes are always made to whatever is referenced/pointed to, never to the reference/pointer itself (modifying a reference is impossible in general).
That is why assigning c a new value inside foo has no effect on c outside foo: the pointer passed to a function is copied.
If you need to modify the pointer, you need to add another level of dereference by passing a pointer reference or a pointer to a pointer.
Following on from comments, the variable c defined in function main is a different variable to the parameter c of function foo. If you want foo to be able to modify main's c, that is modify the address that c's pointer type holds, then you need to pass either a reference or pointer to c to the function instead.
Here is an example that shows the difference between passing c by value (as int *), or by reference (as int ** or int *&). Don't be fooled by the fact that int * is a pointer type, that means that it can receive an int by reference or an int * by value. And since main's c is int * rather than int, main c is being passed by value.
Note the differences in how the functions are called (whether c needs the address operator & in the function call) and the outcome of each function.
#include <iostream>
using namespace std;
void foo_int_ptr(int* c)
{
c=c+1;
}
void foo_int_ptr_ptr(int** c)
{
*c=*c+1;
}
void foo_int_ptr_ref(int*& c)
{
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ptr(&c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ref(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
}
Output:
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808b0, *c=INVALID PTR
&c=0x7e02d81808b8, c=0x7e02d81808b4, *c=INVALID PTR
there is a mistake in your thinking about this ..
int *c = &a;
this doesn't mean that c "contains" address of a, this means that c is a pointer TO the address of a. Passing a pointer to foo() will not do anything.
Assume we have (in C++): MyClass* x = new MyClass(10)
Can someone please explain what 'exactly' happens when compiler parses this statement? (I tried taking a look at the Red Dragon book but couldn't find anything useful).
I want to know what happens in the stack/heap or compiler's symbol table. How compiler keeps track of the type of x variable? How later calls to x->method1(1,2) will be resolved to appropriate methods in MyClass (for simplicity assume there is no inheritance and MyClass is the only class that we have).
MyClass* x is a definition of pointer to object (instance) of type MyClass. Memory for that variable is allocated according to the place of its definition: if it is defined in the method, and is a local variable, stack is used. And it is memory to store the address.
Then expression new MyClass(10) is a command to allocate memory in heap for an object (instance) itself and return address to be stored in x. To fill the memory of new object MyClass (set up its initial state) special method (at least one) is executed automatically - constructor (or several in some cases) - that receives value 10 in your example.
Because C++ allows inheritance (this is also the reason for the execution of several constructors when an instance created) there are some mechanism to determine which method should be exactly called. You should read somewhere about Virtual method table.
In the simplest case (without inheritance), type of variable x (pointer to object of type MyClass) provide all necessary information about object structure. So, x->method1(1,2) or (*x).method1(1,2) provide call of member method1 to execute it with parameters 1 and 2 (stored in stack) as well as with data that form the state of object (stored in heap) and available by this pointer inside any non-static member of class. The method itself, of course, not stored in the heap.
UPDATE:
You can make example to make same experiments, like:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
private:
int innerData;
long long int lastValue;
public:
MyClass() // default constructor
{
cout << "default constructor" << endl;
innerData = 42;
lastValue = 0;
}
MyClass(int data) // constructor with parameter
{
cout << "constructor with parameter" << endl;
innerData = data;
lastValue = 0;
}
int method1(int factor, int coefficient)
{
cout << "Address in this-pinter " << this << endl;
cout << "Address of innerData " << &innerData << endl;
cout << "Address of lastValue " << &lastValue << endl;
cout << "Address of factor " << &factor << endl;
lastValue = factor * innerData + coefficient;
return lastValue;
}
};
int main(void)
{
MyClass* x = new MyClass(10);
cout << "addres of object " << x << endl;
cout << "addres of pointer " << &x << endl;
cout << "size of object " << sizeof(MyClass) << endl;
cout << "size of pointer " << sizeof(x) << endl;
x->method1(1, 2);
}
C++ is indeed a bit nasty, and this already started in C. Just look at the first 3 tokens : MyClass * x. The compiler has to look up MyClass to determine that this is not a multiplication. Since it is a type, it shouldn't look up x either, but add x to the symbol table right there (really can't be delayed). In the ideal world of simple-to-parse languages, there would be no need to keep the symbol table up to date for every token parsed.
After the definition of x, the = signals an initializing expression. That's an easy one to parse: new is unambiguously a keyword, it's not a placement new and the type being created is right there.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
if we create a class like this :
class Sales_data
{
std::string isbn() const {return bookNo;}
std::string bookNo;
};
And we make a object total;
Sales_data total;
total.isbn();
The C++ Primer, fifth edition, says (page 258),"when we call a member function, this is initialized with the address of the object on which the function was invoked "
,it like this:
Sales_data::isbn(&total)
and the book also write,we can get the bookNo like :
std::string isbn()const {return this->bookNo;}
I think the implicit parameter "this" just like a pointer,
but i can't see it type,would anybody help me point what wrong i think and what should i do to understand the implicit parameter 'this' and this parameter works for?
#Jason C
my extra question:
this is a pointer,so it behave like a normal pointer,
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1;
int * b = &a;
cout << "the b is " << b << endl;
cout << "the &a is " << &a << endl;
cout << "the *b is " << *b << endl;
cout << "the &b is" << &b << endl;
return 0;
}
on my computer the output is :
the b is 0110FCEC
the &a is 0110FCEC
the *b is 1
the &b is0110FCE0
then ,What's the use of the type of the pointer.
this is not a parameter, it is a way for an object to refer to itself.
If you use visual studio or any modern IDE you can check that this has the same type as the class of which it is a member of.
There is a good book called "The C++ Object Model" by Stanley B. Lippman which can help understand.
Even if not defined as such in the standard, every implementation I am aware of makes this an implicit parameter to a member function and can be viewed as such.
In C++, you do
object->function () ;
In contrast, in Ada the syntax is
function (object) ;
The object is then an explicit parameter to the member function. The this variable is a product of C++'s member calling syntax. Instead of the programmer having to explicitly declare a parameter identifying the object (as in Ada), C++ does this automatically for you (this).
In most implementations, C++ parameters are bound to offsets to locations on the stack or to registers. This is implemented in the very same way as other parameters (either bound to a stack offset or a register).
this is a pointer to whatever instance of an object the member function is being called on (note that there is no this in static member functions or non-member functions, then).
In your case, it is either a Sales_data * or const Sales_data * depending on the context. Inside isbn(), it is the latter.
This (contrived) example illustrates its value:
class Example {
public:
void function (Example *x);
};
void Example::function (Example *x) {
if (x == this)
cout << "x is this!" << endl;
else
cout << "x is not this." << endl;
}
Now if we do:
Example a;
Example *b = new Example();
a.function(&a); // outputs "x is this!"
b->function(b); // outputs "x is this!"
a.function(b); // outputs "x is not this!"
b->function(&a); // outputs "x is not this!"
Also, since it's a pointer to the "current" instance of the object:
class Example2 {
public:
int k;
void function ();
};
void Example2::function () {
k = 42;
this->k = 42; // does the same thing as above!
}
I have a below code. Every time Constructor is called, I increase a counter and the counter is decreased every time Destructor is called. After instantiating three class objects, I tried printing out the counter value. Then I tried printing out the counter value again after deleting one of the objects. The expected values were 4 and 3, but instead I get 2 and 1.
I actually tried printing out something within the Constructor and Destructor to observe how many times they were actually called, but surprisingly Destructor was called several times in addition to the time when I called "delete object". Is it because the Destructor is called automatically? If so, is there any way to turn the feature off to test my code?
** The code originally has Add and Mult functions in the class, but I omitted here because the details of the functions seem irrelevant here.
#include <iostream>
using namespace std;
class Complex{
private:
double x, y;
static int count;
Complex Add(Complex como)
{
Complex t;
t.x=x+como.x;
t.y=y+como.y;
return t;
}
Complex Mul(Complex como)
{
Complex t;
t.x=(x*como.x)-(y*como.y);
t.y=(y*como.x)+(x*como.y);
return t;
}
public:
Complex(double a=0, double b=0) : x(a), y(b) {count++;}
~Complex() {count--;}
void Print() {cout << "(" << x << ", " << y << ")" << endl;}
static int GetCount() {return count;}
};
int Complex::count=0;
int main()
{
Complex com1(1.0, 2.0), com2(3.0, 4.0);
Complex com3;
com1.Print(); cout << endl;
com2.Print(); cout << endl;
com3 = com1.Add(com2); com3.Print(); cout << endl;
Complex *pcom4 = new Complex;
*pcom4 = com1.Mul(com2); pcom4->Print(); cout << endl;
cout << "#complex numbers = " << com1.GetCount() << endl;
delete pcom4;
cout << "#complex numbers = " << com1.GetCount() << endl;
return 0;
}
In C++ you can construct objects in three ways:
using the "constructor"
using the "copy constructor"
using the "move constructor"
If don't define them the compiler will automatically write the code for you (unless you stop it from doing that explicitly).
Your method Mul and Add are accepting the other complex number by value and this means that a copy constructor call will be used to copy the argument of the call.
The automatic synthesized copy constructor doesn't increment the counter.
Your methods are taking Complex objects as parameters (not references to existing objects), so new objects are being created for each call and are destroyed at the end of the call.
I would like to use parameter in C++ to store back whatever value/object.
In this example, I try to store the value from the global variable as a simplified example.
This code doesn't work,
int value = 20;
void returnPointer2(int* hello)
{
hello = &value;
}
// It changes nothing
int value2 = 100;
returnPointer2(&value2);
cout << value2 << endl;
as I needed double pointer.
void returnPointer3(int** hello)
{
*hello = &value;
}
int* vp2 = new int();
*vp2 = -30;
returnPointer3(&vp2);
cout << *vp2 << endl; // expects 20
I reminded of the reference, and I can use pointer reference to get the same result.
void returnPointer4(int* & hello)
{
cout << "value : " << value;
hello = &value;
}
int* vp3 = new int();
*vp3 = -130;
returnPointer4(vp3); // also expects 20, but much simpler to use
cout << "better : " << *vp3 << endl;
I tried with double &, and it compiles.
void returnPointer5(int&& hello)
{
cout << "value : " << value;
hello = value;
}
However, it doesn't compile with the input of integer variable.
int vp4 = 123;
returnPointer5(vp4); // also expects 20, but even more simpler to use
cout << "best : " << vp4 << endl;
This is an error message.
pointer_return.cpp:31:6: error: initializing argument 1 of 'void returnPointer5(int&&)'
void returnPointer5(int&& hello)
I happened to know about move, and it works with this code.
int vp4 = 123;
returnPointer5(move(vp4)); // also expects 20, but much simpler to see
cout << "best : " << vp4 << endl;
What's the magic/logic behind this move function?
There is a lot of stuff getting mixed in here, but to keep it simple I'll address your root question.
&& is nothing at all like **.
&& is an rvalue reference, while ** is a pointer to a pointer.
As a second point, you are declaring in your function name what you want to do: returnPointer4.
You want to have a pointer to an integer returned back. int*& is the correct syntax for having a reference to a pointer.
Reading over your question again, why don't you use the following:
int& returnGlobalReference() {
return value;
}
Then in your other function:
int& value2 = returnGlobalReference();
The first attempt makes the classic mistake of passing a pointer by value, modifying its address in the function and expecting what it points to to change.
As mentioned in the comments,
void returnPointer2(int* hello)
{
hello = &value; // don't do this, it only modifies what the
// pointer hello, which resides in the stack, points to
*hello = value; // do this instead. even though hello still resides in the
// stack, you're modifying the location that hello points to,
// which was your original intention
}
why do you want to pass pointers however? is the static variable not available when you call the function? (perhaps, different files?)
The magic of std::move is:
The actual declaration for std::move is somewhat more involved, but at its heart, it's just a static_cast to an rvalue reference.
Taken from here.
As Jeffery Thomas already said, a && is not a reference to a reference, but a reference to a rvalue.