7 Replies - 367 Views - Last Post: 26 May 2012 - 12:19 AM Rate Topic: -----

#1 indyarocks  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 104
  • Joined: 07-March 12

Preventing main from changing private variable, when ref is used

Posted 25 May 2012 - 06:30 PM

Hi,
This is interesting, we can actually change the private variable of a class from main.
class c
{public:
 c(int x = 0):n(x) {}
 int & GetRN() { return n;}
 private:
 int n;
};

int main()
{
 c x;
 int & a = x.GetRN();
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
 a = 5;
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
return 0;
}

And the output is:
a = 0
x.GetRN() = 0
a = 5
x.GetRN() = 5


To prevent this, I have tried to use "const" keyword in GetRN() accessor method , so that if a user does int &a = x.GetRN(), he/she won't be able to change the private variable "n" from outside the class.
class c
{public:
 c(int x = 0):n(x) {}
 int & GetRN() const { return n;}
 private:
 int n;
};

int main()
{
 c x;
 int a = x.GetRN();
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
 a = 5;
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
return 0;
}

Error:
t.cpp: In member function 'int& c::GetRN() const':
Line 4: error: invalid initialization of reference of type 'int&' from expression of type 'const int'
compilation terminated due to -Wfatal-errors.

If I remove const from line 4, everything goes well and fine as shown in my first code. Does it mean that we can't return a reference to a variable when the function is supposed to be "const" ?

This post has been edited by indyarocks: 25 May 2012 - 06:30 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Preventing main from changing private variable, when ref is used

#2 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5535
  • View blog
  • Posts: 11,861
  • Joined: 02-June 10

Re: Preventing main from changing private variable, when ref is used

Posted 25 May 2012 - 06:44 PM

Do you know what "const" is? It's short for constant: As in unchanging.

Anything marked 'const' is turned into a fixed value when the application is compiled.

In other words, if you have:

const bob = 5;

At compile time every place you have "bob" will be replaced with an actual 5. It stops being a variable. Therefore you can't later change it. You would be saying 5 now equals 7.



Next, why would you have to return it? If you sent it by reference they your method can change it all it wants and just end - The variable you reference going into the method is changed, not a copy of it. So the calling method can just continue to use the referenced variable with its new value without doing anything special.

This post has been edited by tlhIn`toq: 25 May 2012 - 06:44 PM

Was This Post Helpful? 0
  • +
  • -

#3 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: Preventing main from changing private variable, when ref is used

Posted 25 May 2012 - 06:48 PM

you have to return a constant reference to do this

const int & GetRN() const { return n;}



the 'const' you added tells the compiler that that method dosn't allow for the modification of state. however when you return a mutable reference to data from the class this is violated so the compiler issues an error.

you *could* drop the const that comes after the arguments but it's good practice to have to have and allows for usage of that method if a constant reference/pointer of that class is used.

the 'const' after the arguments states that that method doesn't change or allow change of an instances of a class; hence it can be used with constant references and constant pointers

the const that modifies the type returned dictates that the reference returned can't be mutated and hence allows for that method to be a constant method.

also, if you *know* that you will only be using an 'int' for a particulate method then don't worry about constant references. they don't help any with small values.

Quote

Anything marked 'const' is turned into a fixed value when the application is compiled.


nope, 'const' values can be determined at run-time. C++11's 'constexpr' is known at compile time.

for instance:

int foo(int x) {
   cosnt int y = x * 2;
   return y;
}
int main() {
   int x;
   std::cin>>x;
   std::cout<<foo(x);
}



on the other hand if you used 'constexpr' you would get an error

int foo(int x) {
   cosntexpr int y = x * 2; //error
   return y;
}
int main() {
   int x;
   std::cin>>x;
   std::cout<<foo(x);
}


This post has been edited by ishkabible: 25 May 2012 - 06:56 PM

Was This Post Helpful? 3
  • +
  • -

#4 indyarocks  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 104
  • Joined: 07-March 12

Re: Preventing main from changing private variable, when ref is used

Posted 25 May 2012 - 07:05 PM

Thanks tlhIn. Though I know what "const" stands for, I did not know it is replaced at the compile time. The program I have written, was to learn and get understanding of, how to twist and turn around.

Ishkabible: Thanks a lot. Precise explanation. I wish I could give two points :) Few things to just confirm my understanding:
1. You mean here, if a accessor method is "const" i.e int & GetRN() const { return n;} and if we return by "pointer" or "reference" , then we must add "const" as in ,const int & GetRN() const { return n;} ?
2. The const after GetRN() implies, GetRN can't change any variable of class. It can just access it. And the "const" before return value, i.e. const int & GetRN() , implies the value returned can't be changed later.
3. Can we have any function, which can't change the class members but can return reference to a class memeber, which can be changed later ? (Similar to my question 1).

Once again, Thanks tlhIn and Ishka. You guys make my learning more joyful. :)
Was This Post Helpful? 0
  • +
  • -

#5 sepp2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2118
  • View blog
  • Posts: 3,244
  • Joined: 21-June 11

Re: Preventing main from changing private variable, when ref is used

Posted 25 May 2012 - 11:55 PM

View Postindyarocks, on 26 May 2012 - 04:05 AM, said:

I did not know it is replaced at the compile time.


It isn't - at least not in general. If a value can be known at compile time, it usually will be replaced at compile time in places where it makes sense. But there's no requirement that consts be known at compile time or that consts that are known at compile time are only used in contexts where they can be replaced at compile time.

For example it's perfectly legal to take the address of (or, as you're doing in this case, create a reference to) a const variable. That's one case where it's impossible to replace the variable at compile time.


Quote

1. You mean here, if a accessor method is "const" i.e int & GetRN() const { return n;} and if we return by "pointer" or "reference" , then we must add "const" as in ,const int & GetRN() const { return n;} ?


Only if you're returning a pointer or reference to a member of the object the method is called on (or a member of a member etc.). It would be perfectly legal to e.g. return a pointer or reference to a global variable. Or a point to memory that the method just allocated with new.

The contract is that the method does not allow modification of the object. Returning a non-const reference or pointer to something inside the object allows modification of the object. Returning a non-const pointer or reference to something else does not.

Quote

2. The const after GetRN() implies, GetRN can't change any variable of class. It can just access it. And the "const" before return value, i.e. const int & GetRN() , implies the value returned can't be changed later.


That's correct.

Quote

3. Can we have any function, which can't change the class members but can return reference to a class memeber, which can be changed later ? (Similar to my question 1).


No. Though of course you can have a function which doesn't change class members, but returns a reference. There's no way to let the compiler enforce that though. I'm not sure what the use case would be of that.
Was This Post Helpful? 3
  • +
  • -

#6 indyarocks  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 104
  • Joined: 07-March 12

Re: Preventing main from changing private variable, when ref is used

Posted 26 May 2012 - 12:07 AM

Thanks Sepp. Nice explanation. Reading all the explanation, I did not understand, why my second program failed ?

class c
{public:
 c(int x = 0):n(x) {}
 int & GetRN() const { return n;}
 private:
 int n;
};

int main()
{
 c x;
 int a = x.GetRN();
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
 a = 5;
 cout << "a = " << a << endl;
 cout << "x.GetRN() = " << x.GetRN() << endl;
return 0;
}

Here, I'm just returning a reference to a variable, using GetRN(). Is it because, GetRN() is defined as constant, and returning it as reference, will make it vulnerable to other class/function ?
Error is:
t.cpp: In member function 'int& c::GetRN() const':
Line 4: error: invalid initialization of reference of type 'int&' from exp<b></b>ression of type 'const int'
compilation terminated due to -Wfatal-errors.

This post has been edited by indyarocks: 26 May 2012 - 12:08 AM

Was This Post Helpful? 0
  • +
  • -

#7 sepp2k  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2118
  • View blog
  • Posts: 3,244
  • Joined: 21-June 11

Re: Preventing main from changing private variable, when ref is used

Posted 26 May 2012 - 12:18 AM

View Postindyarocks, on 26 May 2012 - 09:07 AM, said:

Here, I'm just returning a reference to a variable, using GetRN(). Is it because, GetRN() is defined as constant, and returning it as reference, will make it vulnerable to other class/function ?


Yes. As I said the contract of a const-method is that it must not allow any part of the object it is called on to be changed. Returning a non-const pointer or reference to a member violates that contract because the caller might change the object through that pointer or reference.

Another way to think of it is that a const method is one that can be called on a const object. And a const object must not ever be changed. So if a const method allows anything that shouldn't be done on a const-object, the method is invalid. For example having a const method that returns a non-const reference would allow this:

const c myC(42);
myC.GetRN() = 23; // Changes member variable of const object. That's illegal



Since that is invalid (and would invoke UB), it is not legal for a const method to return a non-const pointer or reference. So it doesn't compile.
Was This Post Helpful? 2
  • +
  • -

#8 indyarocks  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 104
  • Joined: 07-March 12

Re: Preventing main from changing private variable, when ref is used

Posted 26 May 2012 - 12:19 AM

Thanks a lot sir. :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1