0

as I know in c++ when you pass a variable by reference means that we pass the very variable not a copy of it. so if a function that takes a refernce as a parameter we know that any change that that function does on the parameter will affect the original variable(variable passed in). but I'm stuck now: I have a member function that takes a reference to int this member function void DecrX(int &x) decrements x when it is called. the problem i get is that the original variable always never affected???!!! eg:

#include <iostream> using namespace std; class A { public: A(int &X):x(X){} int &getX(){return x;} void DecrX(){--x;} void print(){cout<<"A::x= "<<x<<endl<<endl;} private: int x; }; int main() { int x=7; cout<<"x= "<<x<<endl; A a(x);//we passed the x by reference a.DecrX();// here normally DecrX() affect the original x a.print();//here it is ok as we thought a.DecrX(); a.DecrX(); a.print(); cout<<"x= "<<x<<endl;//why x is still 7 not decremented cout<<endl; return 0; } 

5 Answers 5

3

You can make this problem easier for yourself to understand by being a little more verbose, specifically, give your member variables more distinct names.

class A { public: A(int& x) : m_x(x) {} const int& getX() const { return m_x; } void DecrX() { --m_x; } void print() {cout << "A::m_x= " << m_x << endl << endl;} private: int m_x; }; 

Now, lets look at this more carefully. "m_x" (member x) is of type "int". It's not a reference. It's a value.

A(int& x) 

Declares a constructor which takes a reference to a variable and calls this reference "x".

: m_x(x) 

Initializes member x, an integer value, with the value of the reference called x.

The problem is that your member m_x is itself a value and not a reference.

class A { public: A(int& x) : m_x(x) {} const int& getX() const { return m_x; } void DecrX() { --m_x; } void print() {cout << "A::m_x= " << m_x << endl << endl;} private: int& m_x; }; 

BEWARE: Creating objects which take references to things can be a nightmare.

#include <iostream> class A { public: A(int& x) : m_x(x) {} const int& getX() const { return m_x; } void DecrX() { --m_x; } void print() { std::cout << "A::m_x= " << m_x << std::endl << std::endl; } private: int& m_x; }; A calculateStuffAndReturnAnAForMe(int x, int y) { int z = x + y; A a(z); return a; } int main() { A badData = calculateStuffAndReturnAnAForMe(5, 10); badData.print(); // badData's m_x is a reference to z, which is no-longer valid. std::string input; std::cout << "Enter your name: "; std::cin >> input; std::cout << std::endl << "You entered: " << input << std::endl; badData.print(); } 

In this case, the "a" we return has a reference to stack-variable "z" but "z" goes away when we leave the function. The result is Undefined Behavior.

See live demo: http://ideone.com/T279v7

Sign up to request clarification or add additional context in comments.

4 Comments

so does this mean tha z being a local varaible to claculateStuffAndReturnAnAForMe(): each change occurs to the original variable (z) will affect the member data of class A (m_x) and vice versa? (the destruction of z will affect A::m_x and any change class A's member functions do on m_x will affect z)!!!
When we say "m_x references z" the compiler actually uses a pointer, call it xRef, pointing to "&z". When we use "m_x" the compiler substitutes in "*xRef". When we leave calculateStuff, "z" goes out of scope and because its on the stack it's location will be re-used by new variables/function calls. m_x's pointer, xRef, continues to point to that location though. So you have to be very careful when you take references to things that your reference doesn't outlive your object.
Here is a really great explanation of the problem with references to things that go out of scope: stackoverflow.com/questions/6441218/…
it is as if we write: class A{public: A(int x): m_X(x){} int getM_X()const {return m_x;} private: int &m_X;}; int main(){A a(7); cout<<"m_x= "<<a.getM_x()<<endl;} the problem as I guess: m_x which is a member variable of A is a reference to the local varaible int x so after the constructor returns m_x is still pointing to x and x has been destroyed being a stack varaible(local) so m_X has not a correct value. maybe it is a really nightmare
1

In cout<<"x= "<<x<<endl; you print the local variable of main(), whereas in a.print() lines you print the local variable x of object a, which the member function DecrX() decreases.

Comments

1

You're modifying a copy not the original not itself, so the original will not be changed. Read comments:

A(int &X) : x (X) {} // This copies modifiable `X` into `x`. | ^ | | +--+ void DecrX(){--x;} // This decrements `x` not referenced `X` 

To have the ability of modifying the original variable, you should declare a reference:

class A { public: A(int &X):x(X){} void DecrX(){--x;} private: int &x; // <<------------ A reference ^ }; 

Be careful, life time of passed variable should be longer than the receiver object of A.

5 Comments

ok thanx I got it. so does this mean A::x is not the same variable int x (passed in) in memory?
@raindrop7: In your code, yes, they're not the same. But in the second code that I wrote int &x; will store a reference to the original x.
ok thnx. I never saw a reference declared as a member data. could you say if we declare a pointer as member data will do the same as you declared the reference int &x?
@raindrop7: Yes, a pointer can do same thing, but it's strongly recommended to avoid pointers, a reference is less dangerous to use. Read last sentence in my answer.
at last could you explain the difference between A(int x) and A(int &x) knowing that A has-a int m_x as a member data not a reference????
1

The problem is that the fact that your constructor takes variable by reference is irrelevant here:

class A { public: A(int &X):x(X){} // <-- initializes member x by copying passed argument void DecrX(){--x;} // <-- decrements member of class A ... int x; }; 

to achieve what you actually described, you need to define member x as a reference as well:

int& x; 

"if we declare a pointer as member data will do the same as you declared the reference int &x?"

The pointer is initialized using an address. Important to realize is that NULL is perfectly valid value while reference can not be initialized by other means than using valid variable / object. Note that once you declare member x as a reference, you introduce a constraint that instance of class A can not be created without valid int variable. Have a look at: Should I prefer pointers or references in member data?

Comments

0

The problem here is that you pass the reference, but then assign it to the class member x. Doing this will not keep the reference. And the x class member and the x in the main are totally unrelated. I hope this makes sense. To fix this, you could make the class member x a pointer.

3 Comments

ok thnx alot. but the last question: what is the point in writting A(int &x) and A(int x) if I declare int m_x as member data???
You mean why use A(int &x) when the reference is lost anyway when using int m_x? Well, one case where you could do this is when the parameter cointains an instance of a big class with many data. When you use A(x), it will copy the whole object into the function, but when using A(&x) it will only copy a refence. So passsing a parameter by reference is faster when you deal with big objects.
ok thnx it is clear now. and does this mean any change to "int &x" will affect the original variable?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.