Using Variable When Declaring Constructors [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
This is confusing me:
class CDummy
{
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (&param == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
int main ()
{
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
{
cout << "yes, &a is b";
}
return 0;
}
In C & usually means the address of a var. What does it mean here? Is this a fancy way of pointer notation?
The reason I am assuming it is a pointer notation because this is a pointer after all and we are checking for equality of two pointers.
I am studying from cplusplus.com and they have this example.

The & has more the one meanings:
1) take the address of a variable
int x;
void* p = &x;
//p will now point to x, as &x is the address of x
2) pass an argument by reference to a function
void foo(CDummy& x);
//you pass x by reference
//if you modify x inside the function, the change will be applied to the original variable
//a copy is not created for x, the original one is used
//this is preffered for passing large objects
//to prevent changes, pass by const reference:
void fooconst(const CDummy& x);
3) declare a reference variable
int k = 0;
int& r = k;
//r is a reference to k
r = 3;
assert( k == 3 );
4) bitwise and operator
int a = 3 & 1; // a = 1
n) others???

To start, note that
this
is a special pointer ( == memory address) to the class its in.
First, an object is instantiated:
CDummy a;
Next, a pointer is instantiated:
CDummy *b;
Next, the memory address of a is assigned to the pointer b:
b = &a;
Next, the method CDummy::isitme(CDummy &param) is called:
b->isitme(a);
A test is evaluated inside this method:
if (&param == this) // do something
Here's the tricky part. param is an object of type CDummy, but &param is the memory address of param. So the memory address of param is tested against another memory address called "this". If you copy the memory address of the object this method is called from into the argument of this method, this will result in true.
This kind of evaluation is usually done when overloading the copy constructor
MyClass& MyClass::operator=(const MyClass &other) {
// if a programmer tries to copy the same object into itself, protect
// from this behavior via this route
if (&other == this) return *this;
else {
// otherwise truly copy other into this
}
}
Also note the usage of *this, where this is being dereferenced. That is, instead of returning the memory address, return the object located at that memory address.

Well the CDummy& param that is declared as a parameter of the function CDummy::isitme is actually a reference which is "like" a pointer, but different. The important thing to note about references is that inside functions where they are passed as parameters, you really have a reference to the instance of the type, not "just" a pointer to it. So, on the line with the comment, the '&' is functioning just like in C, it is getting the address of the argument passed in, and comparing it to this which is, of course, a pointer to the instance of the class the method is being called on.

Related

I don't understand what's the different between a '&' in and out of a class object's variable parentheses [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
This is confusing me:
class CDummy
{
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (&param == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
int main ()
{
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
{
cout << "yes, &a is b";
}
return 0;
}
In C & usually means the address of a var. What does it mean here? Is this a fancy way of pointer notation?
The reason I am assuming it is a pointer notation because this is a pointer after all and we are checking for equality of two pointers.
I am studying from cplusplus.com and they have this example.
The & has more the one meanings:
1) take the address of a variable
int x;
void* p = &x;
//p will now point to x, as &x is the address of x
2) pass an argument by reference to a function
void foo(CDummy& x);
//you pass x by reference
//if you modify x inside the function, the change will be applied to the original variable
//a copy is not created for x, the original one is used
//this is preffered for passing large objects
//to prevent changes, pass by const reference:
void fooconst(const CDummy& x);
3) declare a reference variable
int k = 0;
int& r = k;
//r is a reference to k
r = 3;
assert( k == 3 );
4) bitwise and operator
int a = 3 & 1; // a = 1
n) others???
To start, note that
this
is a special pointer ( == memory address) to the class its in.
First, an object is instantiated:
CDummy a;
Next, a pointer is instantiated:
CDummy *b;
Next, the memory address of a is assigned to the pointer b:
b = &a;
Next, the method CDummy::isitme(CDummy &param) is called:
b->isitme(a);
A test is evaluated inside this method:
if (&param == this) // do something
Here's the tricky part. param is an object of type CDummy, but &param is the memory address of param. So the memory address of param is tested against another memory address called "this". If you copy the memory address of the object this method is called from into the argument of this method, this will result in true.
This kind of evaluation is usually done when overloading the copy constructor
MyClass& MyClass::operator=(const MyClass &other) {
// if a programmer tries to copy the same object into itself, protect
// from this behavior via this route
if (&other == this) return *this;
else {
// otherwise truly copy other into this
}
}
Also note the usage of *this, where this is being dereferenced. That is, instead of returning the memory address, return the object located at that memory address.
Well the CDummy& param that is declared as a parameter of the function CDummy::isitme is actually a reference which is "like" a pointer, but different. The important thing to note about references is that inside functions where they are passed as parameters, you really have a reference to the instance of the type, not "just" a pointer to it. So, on the line with the comment, the '&' is functioning just like in C, it is getting the address of the argument passed in, and comparing it to this which is, of course, a pointer to the instance of the class the method is being called on.

how to properly pass a pointer with the address of a variable from a function into another function that takes in a reference [duplicate]

Is the following code (func1()) correct if it has to return i? I remember reading somewhere that there is a problem when returning a reference to a local variable. How is it different from func2()?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
This code snippet:
int& func1()
{
int i;
i = 1;
return i;
}
will not work because you're returning an alias (a reference) to an object with a lifetime limited to the scope of the function call. That means once func1() returns, int i dies, making the reference returned from the function worthless because it now refers to an object that doesn't exist.
int main()
{
int& p = func1();
/* p is garbage */
}
The second version does work because the variable is allocated on the free store, which is not bound to the lifetime of the function call. However, you are responsible for deleteing the allocated int.
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
Typically you would wrap the pointer in some RAII class and/or a factory function so you don't have to delete it yourself.
In either case, you can just return the value itself (although I realize the example you provided was probably contrived):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
Note that it's perfectly fine to return big objects the same way func3() returns primitive values because just about every compiler nowadays implements some form of return value optimization:
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
Interestingly, binding a temporary to a const reference is perfectly legal C++.
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
A local variable is memory on the stack, and that memory is not automatically invalidated when you go out of scope. From a function deeper nested (higher on the stack in memory), it’s perfectly safe to access this memory.
Once the function returns and ends though, things get dangerous.
Usually the memory is not deleted or overwritten when you return, meaning the memory at that address is still containing your data - the pointer seems valid.
Until another function builds up the stack and overwrites it.
This is why this can work for a while - and then suddenly cease to function after one particularly deeply nested set of functions, or a function with really huge sized or many local objects, reaches that stack-memory again.
It even can happen that you reach the same program part again, and overwrite your old local function variable with the new function variable. All this is very dangerous and should be heavily discouraged.
Do not use pointers to local objects!
A good thing to remember are these simple rules, and they apply to both parameters and return types...
Value - makes a copy of the item in question.
Pointer - refers to the address of the item in question.
Reference - is literally the item in question.
There is a time and place for each, so make sure you get to know them. Local variables, as you've shown here, are just that, limited to the time they are locally alive in the function scope. In your example having a return type of int* and returning &i would have been equally incorrect. You would be better off in that case doing this...
void func1(int& oValue)
{
oValue = 1;
}
Doing so would directly change the value of your passed in parameter. Whereas this code...
void func1(int oValue)
{
oValue = 1;
}
would not. It would just change the value of oValue local to the function call. The reason for this is because you'd actually be changing just a "local" copy of oValue, and not oValue itself.

MSVC error C4172 when overloading post-increment operator [duplicate]

Is the following code (func1()) correct if it has to return i? I remember reading somewhere that there is a problem when returning a reference to a local variable. How is it different from func2()?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
This code snippet:
int& func1()
{
int i;
i = 1;
return i;
}
will not work because you're returning an alias (a reference) to an object with a lifetime limited to the scope of the function call. That means once func1() returns, int i dies, making the reference returned from the function worthless because it now refers to an object that doesn't exist.
int main()
{
int& p = func1();
/* p is garbage */
}
The second version does work because the variable is allocated on the free store, which is not bound to the lifetime of the function call. However, you are responsible for deleteing the allocated int.
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
Typically you would wrap the pointer in some RAII class and/or a factory function so you don't have to delete it yourself.
In either case, you can just return the value itself (although I realize the example you provided was probably contrived):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
Note that it's perfectly fine to return big objects the same way func3() returns primitive values because just about every compiler nowadays implements some form of return value optimization:
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
Interestingly, binding a temporary to a const reference is perfectly legal C++.
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
A local variable is memory on the stack, and that memory is not automatically invalidated when you go out of scope. From a function deeper nested (higher on the stack in memory), it’s perfectly safe to access this memory.
Once the function returns and ends though, things get dangerous.
Usually the memory is not deleted or overwritten when you return, meaning the memory at that address is still containing your data - the pointer seems valid.
Until another function builds up the stack and overwrites it.
This is why this can work for a while - and then suddenly cease to function after one particularly deeply nested set of functions, or a function with really huge sized or many local objects, reaches that stack-memory again.
It even can happen that you reach the same program part again, and overwrite your old local function variable with the new function variable. All this is very dangerous and should be heavily discouraged.
Do not use pointers to local objects!
A good thing to remember are these simple rules, and they apply to both parameters and return types...
Value - makes a copy of the item in question.
Pointer - refers to the address of the item in question.
Reference - is literally the item in question.
There is a time and place for each, so make sure you get to know them. Local variables, as you've shown here, are just that, limited to the time they are locally alive in the function scope. In your example having a return type of int* and returning &i would have been equally incorrect. You would be better off in that case doing this...
void func1(int& oValue)
{
oValue = 1;
}
Doing so would directly change the value of your passed in parameter. Whereas this code...
void func1(int oValue)
{
oValue = 1;
}
would not. It would just change the value of oValue local to the function call. The reason for this is because you'd actually be changing just a "local" copy of oValue, and not oValue itself.

how does the ampersand(&) sign work in c++? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
This is confusing me:
class CDummy
{
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (&param == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
int main ()
{
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
{
cout << "yes, &a is b";
}
return 0;
}
In C & usually means the address of a var. What does it mean here? Is this a fancy way of pointer notation?
The reason I am assuming it is a pointer notation because this is a pointer after all and we are checking for equality of two pointers.
I am studying from cplusplus.com and they have this example.
The & has more the one meanings:
1) take the address of a variable
int x;
void* p = &x;
//p will now point to x, as &x is the address of x
2) pass an argument by reference to a function
void foo(CDummy& x);
//you pass x by reference
//if you modify x inside the function, the change will be applied to the original variable
//a copy is not created for x, the original one is used
//this is preffered for passing large objects
//to prevent changes, pass by const reference:
void fooconst(const CDummy& x);
3) declare a reference variable
int k = 0;
int& r = k;
//r is a reference to k
r = 3;
assert( k == 3 );
4) bitwise and operator
int a = 3 & 1; // a = 1
n) others???
To start, note that
this
is a special pointer ( == memory address) to the class its in.
First, an object is instantiated:
CDummy a;
Next, a pointer is instantiated:
CDummy *b;
Next, the memory address of a is assigned to the pointer b:
b = &a;
Next, the method CDummy::isitme(CDummy &param) is called:
b->isitme(a);
A test is evaluated inside this method:
if (&param == this) // do something
Here's the tricky part. param is an object of type CDummy, but &param is the memory address of param. So the memory address of param is tested against another memory address called "this". If you copy the memory address of the object this method is called from into the argument of this method, this will result in true.
This kind of evaluation is usually done when overloading the copy constructor
MyClass& MyClass::operator=(const MyClass &other) {
// if a programmer tries to copy the same object into itself, protect
// from this behavior via this route
if (&other == this) return *this;
else {
// otherwise truly copy other into this
}
}
Also note the usage of *this, where this is being dereferenced. That is, instead of returning the memory address, return the object located at that memory address.
Well the CDummy& param that is declared as a parameter of the function CDummy::isitme is actually a reference which is "like" a pointer, but different. The important thing to note about references is that inside functions where they are passed as parameters, you really have a reference to the instance of the type, not "just" a pointer to it. So, on the line with the comment, the '&' is functioning just like in C, it is getting the address of the argument passed in, and comparing it to this which is, of course, a pointer to the instance of the class the method is being called on.

passing a pointer of a reference/passing a reference of a reference

Do I get a usual pointer as I pass a pointer to a reference of a variable or do i get a pointer to the reference? And what do i get as I pass a reference to a reference?
I am using the stack implementation of the standard library in a class, and i want to have some wrapper methods to prevent illegal access of the stack, but i am getting strange segfaults which i narrowed down to my getter-methods considering the stack.
Should those methods give back a clean reference/pointer to the original variable stored in the stack?
int& zwei() { return stack.top() };
and
int* eins() { return &stack.top() };
There is no such thing as a "pointer to a reference". References are aliases, and so taking the address of any of them will give a pointer to the same object:
int a;
int & b = a;
assert(&a == &b);
Your functions both return a valid result provided that the stack object is still alive in the scope of the function return.
std::stack<int> s;
int & foo() { return s.top(); } // OK, maybe
int * goo() { return &s.top(); } // ditto
int & boo() { std::stack<int> b; return b.top(); } // No! Dangling reference!
You should also check that the stack isn't empty, in which case top() is not valid.
(I should also council against calling a variable by the same name as a type, even though the type's name is std::stack.)