Question on Constant Variables

Discussion in 'C++' started by fabian.lim@gmail.com, Sep 9, 2008.

  1. Guest

    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??

    Thanks in advance

    //********************************************************
    // 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++;
    }
    }

    };
     
    , Sep 9, 2008
    #1
    1. Advertising

  2. mqrk Guest

    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)
     
    mqrk, Sep 9, 2008
    #2
    1. Advertising

  3. Ian Collins Guest

    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.

    > Thanks in advance
    >
    > //********************************************************
    > // 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.
     
    Ian Collins, Sep 9, 2008
    #3
  4. James Kanze Guest

    On Sep 9, 9:31 am, Ian Collins <> wrote:
    > 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:
    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
     
    James Kanze, Sep 9, 2008
    #4
  5. Guest

    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++;
    }
    }

    };
     
    , Sep 9, 2008
    #5
  6. mqrk Guest

    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.
     
    mqrk, Sep 9, 2008
    #6
  7. 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::eek: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, Sep 9, 2008
    #7
  8. Re: Question on Constant Variables (typo fix)

    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
     
    Andrey Tarasevich, Sep 9, 2008
    #8
  9. Guest

    Re: Question on Constant Variables (typo fix)

    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 <>
    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
     
    , Sep 10, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher M. Lusardi
    Replies:
    1
    Views:
    4,111
  2. Martin Magnusson
    Replies:
    2
    Views:
    519
    John Harrison
    Oct 8, 2004
  3. Tor Erik Soenvisen
    Replies:
    14
    Views:
    576
    Tim Roberts
    Nov 23, 2006
  4. Replies:
    4
    Views:
    348
    Keith Thompson
    Dec 14, 2006
  5. Replies:
    13
    Views:
    12,966
    Kai-Uwe Bux
    Jan 22, 2007
Loading...

Share This Page