Velocity Reviews > C++ > Question on Constant Variables

Question on Constant Variables

fabian.lim@gmail.com
Guest
Posts: n/a

 09-09-2008
Hi,

I have a question on constant variables. In the following code
snippet, I have a function assign() that takes in an iterator to the
private variable v, the number of stuff to assign (int n), and the
information to assign (a const pointer to a class object
Vector<TYPE>.

According to the arrow below, I put a const keyword in the function.
To my knowledge, this means that all private variables in this object
cannot be changed. however, the iterator to the private variable v is
not constant.

Can somebody explain to me why I still can change stuff in the
private variable v??

//************************************************** ******
// Main Vector Class
template <typename TYPE>
class Vector {
vector<TYPE> v;
public:

//************************************************** ******
// Constructors and Destructor
Vector() { };
~Vector(){ };

//************************************************** ******
// vector container functions
void assign(typename vector<TYPE>::iterator itr, const int& n, const
Vector<TYPE>& val) const { <--
for (int k=0; k<n; k++){
*itr = val[k]; itr++;
}
}

};

mqrk
Guest
Posts: n/a

 09-09-2008
Since nobody else has answered yet, I'll go ahead and take a stab at
it. My guess is that the compiler has no possible way of knowing when
it compiles "assign" that itr points to a member of this object.
Correct me if I'm wrong, but this is much like:

#include <iostream>

class A
{
public:
int n;
void foo( int& i) const
{
i = 100;
}
};

int main()
{
A a;
a.n = 5;
a.foo( a.n );
std::cout << a.n << std::endl; // Prints out 100
return 0;
}

"foo" isn't really modifying a data member, just some reference it was
passed (which, in this case, just happens to be a data member)

Ian Collins
Guest
Posts: n/a

 09-09-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Hi,
>
> I have a question on constant variables.

A constant variable is a contradiction!

> In the following code
> snippet, I have a function assign() that takes in an iterator to the
> private variable v, the number of stuff to assign (int n), and the
> information to assign (a const pointer to a class object
> Vector<TYPE>.
>

Where does it do this? Your code only shows the member function assign,
not how it is called.

> According to the arrow below, I put a const keyword in the function.
> To my knowledge, this means that all private variables in this object
> cannot be changed. however, the iterator to the private variable v is
> not constant.
>

Nowhere in the function is v referenced.

> Can somebody explain to me why I still can change stuff in the
> private variable v??
>

You don't appear to be.

>
> //************************************************** ******
> // Main Vector Class
> template <typename TYPE>
> class Vector {
> vector<TYPE> v;
> public:
>
> //************************************************** ******
> // Constructors and Destructor
> Vector() { };
> ~Vector(){ };
>
>
> //************************************************** ******
> // vector container functions
> void assign(typename vector<TYPE>::iterator itr, const int& n, const
> Vector<TYPE>& val) const { <--
> for (int k=0; k<n; k++){
> *itr = val[k]; itr++;
> }
> }
>
> };

--
Ian Collins.

James Kanze
Guest
Posts: n/a

 09-09-2008
On Sep 9, 9:31 am, Ian Collins <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:

> > I have a question on constant variables.

> A constant variable is a contradiction!

One man's variables are another man's constants. But I'm pretty
sure he means a const variable, which can be a (compile time)
constant, and is a variable according to the definition of C++;
within the definition of C++ (or most other languages), the word
"variable" has a very special meaning, which has relatively
little to do with the word's more general meaning (and an
invariant that a given variable doesn't vary makes sense).

> > In the following code snippet, I have a function assign()
> > that takes in an iterator to the private variable v, the
> > number of stuff to assign (int n), and the information to
> > assign (a const pointer to a class object Vector<TYPE>.

> Where does it do this? Your code only shows the member
> function assign, not how it is called.

> > According to the arrow below, I put a const keyword in the
> > function. To my knowledge, this means that all private
> > variables in this object cannot be changed. however, the
> > iterator to the private variable v is not constant.

> Nowhere in the function is v referenced.

Which doesn't mean that he doesn't access it.

> > Can somebody explain to me why I still can change stuff in
> > the private variable v??

> You don't appear to be.

But we don't know. He might access it through some other
expression.

> > //************************************************** ******
> > // Main Vector Class
> > template <typename TYPE>
> > class Vector {
> > vector<TYPE> v;
> > public:

>
> > //************************************************** ******
> > // Constructors and Destructor
> > Vector() { };
> > ~Vector(){ };

>
> > //************************************************** ******
> > // vector container functions
> > void assign(typename vector<TYPE>::iterator itr, const int& n, const
> > Vector<TYPE>& val) const { <--
> > for (int k=0; k<n; k++){
> > *itr = val[k]; itr++;
> > }
> > }
> > };

Just a guess, but I'll bet that his problem is that the iterator
he's passing as an argument refers to v. In which case, he can
modify v. The fact that the function is const doesn't mean that
you can't modify the object; it means that the type of the this
pointer is pointer to const, so lvalue expressions derived from
the this pointer (used explicitly or implicitly) have const
type, and so cannot be used to modify the object without a
const_cast. (The fact that a function is const also means that
you can call it on a const object. If you do so, then any
attempt to modify the object is undefined behavior. But of
course, in this case, he couldn't get a non-const iterator into
the object without a const_cast somewhere along the road
either.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

fabian.lim@gmail.com
Guest
Posts: n/a

 09-09-2008
Hi all,

I guess I didnt ask the question properly. Let me try again. Im
writing a vector class that wraps the STL vector container. Im
considering the situation as follows: Lets say a have a vector Y of 3
elements. I want to assign it to elements 1 to 3 in a vector X. Then i
do X(1,3) = Y. So in this case, the operator overload (const int& i,
const int& j) for object X gets called first, and creates (im not sure
if this is the right name) an iterator class object VectorItr<TYPE>
(lets call it Z), and passing the principle argument of X along. Then
in (b), the consturctor for Z uses a member function of X to access
the begin interator of v, which is private in X. It sets vitr to the
begin iterator of v, and exits the constructor. The overload operator
= gets called next, and calls the function assign in question. Assign
is marked in (c). Then my original question follows:

To my knowledge, this means that all private variables in this
object
cannot be changed. however, the iterator to the private variable v is
not constant.

Can somebody explain to me why I still can change stuff in the
private variable v??

Thanks again, sorry for the first time.

//************************************************** ******
// VectorIterators Class
// this is a class to manage iterators of the Vector Class
template <typename TYPE>
class VectorItr {
typename vector<TYPE>::iterator vitr;
int n;
public:

//assignments

VectorItr<TYPE>& operator=(const Vector<TYPE>& rhs) {
//using the iterator, populate the Vector<TYPE>
rhs.assign(vitr,n,rhs);
return *this; //should i return this?
}

//************************************************** ******
// Constructors and Destructor
VectorItr() { };
~VectorItr(){ };

VectorItr( Vector<TYPE>& val, const int& i, const int& j) { <------
(b)
//this constructor is used to initialize the beginning of the
//iterator, and the number of elements that need to be assigned
vitr = val.begin()+i; n = j-i+1;
}
};

//************************************************** ******
// Main Vector Class
template <typename TYPE>
class Vector {
vector<TYPE> v;
public:

VectorItr<TYPE> operator()(const int& i,const int& j)
<-------- (a)
{
return VectorItr<TYPE> (*this, i, j);
}

//************************************************** ******
// Constructors and Destructor
Vector() { };
~Vector(){ };

//************************************************** ******
// vector container functions
void assign(typename vector<TYPE>::iterator itr, const int& n,
const
Vector<TYPE>& val) const { <----- (c)
for (int k=0; k<n; k++){
*itr = val[k]; itr++;
}
}

};

mqrk
Guest
Posts: n/a

 09-09-2008
If I understand your question correctly, then this analogy should
help:

class A
{
public:
int n;
A( int i ) : n( i ) {}
void foo( A& a ) const { a.n = n; } //fine to modify another A's n
//void bar() const { n = 100; } //Error: can't modify this->n
};

int main()
{
const A a1(10);
A a2( 20 );
a1.foo( a2 );
std::cout << a2.n << std::endl; // Prints out 10
return 0;
}

Sorry if I have again misunderstood the question. That last post was
really confusing.

Andrey Tarasevich
Guest
Posts: n/a

 09-09-2008
(E-Mail Removed) wrote:
>
> Can somebody explain to me why I still can change stuff in the
> private variable v??
>

Firstly, speaking informally, the effect of 'const' keyword used to
qualify a class method applies to _all_ data members of the class,
regardless of whether they are private or not. 'Private' has absolutely
nothing to do with the issue in question. Forget about 'private'.

Secondly, what you seem to misunderstand, is that 'const' qualifier in
C++ can be used to qualify an _access_ _path_ to certain object. When
some access path is const-qualified, it means that you can't normally
modify that object through that specific access path. At the same time
it might be perfectly possible to modify the same object using other,
alternative non-const-qualified access paths.

For example, here

int i = 5;
int* p = &i;
const int* pc = &i;

I have a variable 'i' and two access paths to that variable: '*p' and
'*pc'. The latter is const-qualified, meaning that I can't modify 'i'
through that path

*pc = 42; // ERROR

However, I can easily modify 'i' using the former access path

*p = 42; // OK

and now if I check the const-qualified access path, I'll discover that
'*pc' changed to 42.

When you declare some class method as 'const', that only means that you
can't modify the class data through the 'this' pointer. I.e. the access
path provided by '*this' is const-qualified inside the class method. If
inside your 'assign' you try to directly modify 'this->v', you'll get an
error.

void assign(typename vector<TYPE>::iterator itr, const int& n,
const Vector<TYPE>& val) const // <----- (c)
{
this->v[0] = 42; // ERROR
// or simply
v[0] = 42; // ERROR
}

This happens because of your 'const' at point (c).

However, just like I described before, if you have any alternative
non-const-qualified access paths to the inner data of your class,
there's nothing to prevent you from that data it. That's exactly what
happens in your code. An instance of your 'VectorItr' class created by
'Vector:perator()' is nothing else than an alternative
non-const-qualified access path to the inner data of that 'Vector'
object. You pass that 'VectorItr' instance into the 'Vector::assign'
method and then use it to modify the data

void assign(typename vector<TYPE>::iterator itr, const int& n,
const Vector<TYPE>& val) const // <----- (c)
{
*itr = 42; // OK
}

'const at (c) can't prevent it because it has absolutely nothing to do
with it. You provided 'assign' with a way to circumvent the "protection"
provided by 'const'. It is specifically _you_ who did it, so you really
shouldn't be surprised at all.

--
Best regards,
Andrey Tarasevich

Andrey Tarasevich
Guest
Posts: n/a

 09-09-2008
Andrey Tarasevich wrote:
>
> However, just like I described before, if you have any alternative
> non-const-qualified access paths to the inner data of your class,
> there's nothing to prevent you from that data it.

Should be:

> However, just like I described before, if you have any alternative
> non-const-qualified access paths to the inner data of your class,
> there's nothing to prevent you from modifying that data.

--
Best regards,
Andrey Tarasevich

fabian.lim@gmail.com
Guest
Posts: n/a

 09-10-2008
Dear all,

Thank you everybody who replied on this post. I think I resolved my
confusing.

Thanks again.

On Sep 9, 10:32 am, Andrey Tarasevich <(E-Mail Removed)>
wrote:
> Andrey Tarasevich wrote:
>
> > However, just like I described before, if you have any alternative
> > non-const-qualified access paths to the inner data of your class,
> > there's nothing to prevent you from that data it.

>
> Should be:
>
> > However, just like I described before, if you have any alternative
> > non-const-qualified access paths to the inner data of your class,
> > there's nothing to prevent you from modifying that data.

>
> --
> Best regards,
> Andrey Tarasevich