Insight Into const_cast on const data-members

This is a discussion on Insight Into const_cast on const data-members within the C++ Programming forums, part of the General Programming Boards category; Hi, We had a discussion on this board regarding the usefulness of const_cast. "if a variable is const at its ...

  1. #1
    Registered User
    Join Date
    Dec 2002
    Posts
    103

    Question Insight Into const_cast on const data-members

    Hi,

    We had a discussion on this board regarding the usefulness of const_cast.

    "if a variable is const at its point of definition, the result of
    casting it away are undefined".

    Polymorphic OOP suggested that this rule might not be applicable on non-static const datamembers.

    Below mentioned is the extract of the email-interaction between "Bjarne Stroustrup" and me

    ---------------- My Question --------------------
    Sir,
    You have suggested that

    const int i = 10;

    int *p = const_cast<int *>(&i);

    *p = 20; // Result is undefined

    "if a variable is const at its point of definition, the result of
    casting it away are undefined".

    My question is "are datamembers an exception to to this suggestion?"
    ---------------------------My Question Ends Here ---------------

    -------------- Bjarne Stroustrup's Answer ----------------------

    No, and it's not a "suggestion" its a rule of the language. An
    implementation is allowed to place a const in unwritable memory, such as a code segment, so that the *p=20 causes a run-time hardware exception. This is sometimes done in embedded systems where RAM is scarce and ROM cheaper.

    -------------- Bjarne Stroustrup's Answer Ends Here--------------


    Hope this is of some help to you folks
    Have a wonderful day.... and keep smiling... you look terrific that way
    signing off...
    shiv... as i know him

  2. #2
    Programming Sex-God Polymorphic OOP's Avatar
    Join Date
    Nov 2002
    Posts
    1,078
    This goes back to the same reason that const function parameters can be editted (which was the example that you pointed out). When data is on the stack, it's guaranteed to have a writable memory location. The same goes with data on the heap, or any type of const that can be initialized with a different value at runtime. A nonstatic const datamember which can be initialized differently for each object at runtime must be stored with that structure in each object as defined by the standard. That means that if the object is in writable memory, then the nonstatic const datamember is as well (whether it be on the stack, heap, in data, etc.). The standard states that const data CAN be placed in unwritable memory -- however, if it DID in this case, it would be contradictory. Stroustrup probably thought you meant a const int which is initialized in the class definition (which is in all actuality just a static const).

    Code:
    #include<iostream>
    
    class A
    {
    public:
        A( int a_init );
    public:
        const int a;
    };
    
    A::A( int a_init )
        : a( a_init )
    {
    }
    
    int main()
    {
    
        A Test( 1 );
    
        std::cout << Test.a << std::endl;
    
        *(const_cast<int*>(&Test.a)) = 4;
    
        std::cout << Test.a << std::endl;
    
        return 0;
    }
    Should output:

    1
    4

    While it is possible to do, it's still not recommended.
    Last edited by Polymorphic OOP; 01-15-2003 at 09:55 PM.

  3. #3
    I lurk
    Join Date
    Aug 2002
    Posts
    1,361
    Stroustrup probably thought you meant a const int which is initialized in the class definition (which is in all actuality just a static const).
    Well, why don't you ask him?

    #include<iostream>

    class A
    {
    public:
    A( int a_init );
    public:
    const int a;
    };

    A::A( int a_init )
    : a( a_init )
    {
    }

    int main()
    {

    A Test( 1 );

    std::cout << Test.a << std::endl;

    *(const_cast<int*>(&Test.a)) = 4;

    std::cout << Test.a << std::endl;

    return 0;
    }
    Examples like this don't prove anything. As stroustrup said, this predicament only really apparent in embedded systems.

    Just because that doesn't output undefined results doesn't prove it's defined.

    I'm not saying you're wrong or right. I don't have a stance on this subject, because I honestly don't know. I'd like to see an answer from the man himself.

  4. #4
    Programming Sex-God Polymorphic OOP's Avatar
    Join Date
    Nov 2002
    Posts
    1,078
    Yeah, according to the standard, if it were possible, the data could potentially not be editted, but it is literally impossible in this case to make the const in unwritable memory without going against other things in the standard. It can't get a runtime error because it is in the same place that a nonconst piece of data could be stored. If there was a pointer to the memory not denoted by const (IE if the const was casted away), neither the program nor the "pointer" nor anything else would know if it pointed to const data. It would be completely oblivious, even at runtime.
    Last edited by Polymorphic OOP; 01-15-2003 at 11:08 PM.

  5. #5
    Registered User
    Join Date
    Dec 2002
    Posts
    103

    We can't conclude

    Originally posted by Polymorphic OOP
    Yeah, according to the standard, if it were possible, the data could potentially not be editted, but it is literally impossible in this case to make the const in unwritable memory without going against other things in the standard. It can't get a runtime error because it is in the same place that a nonconst piece of data could be stored. If there was a pointer to the memory not denoted by const (IE if the const was casted away), neither the program nor the "pointer" nor anything else would know if it pointed to const data. It would be completely oblivious, even at runtime.
    Hi Ploymorphic OOP,

    Your observations w.r.t memory being allocated in the writable / non-writable memory understood and well taken.......

    Having said that we can't take a definite stance on this topic with your observations..... everything becomes very relative.

    Its preferable if we take the standards as the "Final Say" and just code things that comply with the standard and never do anything (even if it works) that are not supported / suggested by the standard
    Have a wonderful day.... and keep smiling... you look terrific that way
    signing off...
    shiv... as i know him

  6. #6
    Registered User
    Join Date
    Jan 2003
    Posts
    4

    Cool

    hi,
    I just don't understand.
    Plz check the code below.

    *************************
    int main()
    {
    const int i = 10;

    int *ptr = NULL;
    ptr = const_cast<int*>(&i);

    cout<<*ptr<<endl;

    *ptr = *ptr + 100;

    cout<<*ptr<<endl;
    cout<<i<<endl;
    cout<<ptr<<"\t"<<&i<<endl;

    return 0;
    }
    *******************************

    in this code the value of i does not change.
    i.e. the value of the pointer changes but the cout ing the
    actual value gives the original value back.

    but in case of a const variable in a class this does not happen
    the old value is over written atleast in VC++ compiler this is
    what is happening.

    so whats the difference between a const variable in a main
    and const variable in a class.

    enlighten me please.
    -Newt

  7. #7
    Registered User
    Join Date
    Jan 2003
    Posts
    4
    let me get this straight,
    When I create a constant in main, I am directly initializing it to a constant but in a class the initialization is done per object which means there are multiple copies of that constant variable, hence it can be modified using the const_cast.



    am i getting this right ?
    one more thing do all compliers behave like this or is it specific to MSVC++

  8. #8
    Programming Sex-God Polymorphic OOP's Avatar
    Join Date
    Nov 2002
    Posts
    1,078
    Because you are initializing it to a constant, not a variable.

  9. #9
    Programming Sex-God Polymorphic OOP's Avatar
    Join Date
    Nov 2002
    Posts
    1,078
    Originally posted by newt
    let me get this straight,
    When I create a constant in main, I am directly initializing it to a constant but in a class the initialization is done per object which means there are multiple copies of that constant variable, hence it can be modified using the const_cast.
    Only if you initialize it to a variable on a per object basis.

    If you initialize it in main to a variable the same thing would be true.

    The actual results are not defined by the standard. I was just making the point that in order to comply with other things in the standard, those constants have to have valid writable memory locations (unlike most other types of constants). You still should NOT do it as the results are still "undefined."

  10. #10
    Registered User
    Join Date
    Jan 2003
    Posts
    4

    Question

    hmmm......
    so when ever I create a variable and assign it to a constant the
    constant is modified ( using const_Cast )
    but a literal is hard coded and is not erased.
    so the compiler must be substituting the 10 directly ( from the ROM area) where as in case of the variable it just passes the address of the variable, which IS modifiable...



    Just one more thing then:
    The address stored in the pointer and the address of the constant is the same, so how can two values reside in the same location
    const int i = 10;
    int *ptr = NULL;
    ptr = const_cast<int*>(&i);
    cout<<*ptr<<endl;
    *ptr = *ptr + 100;
    cout<<*ptr<<endl;
    cout<<i<<endl;
    cout<<ptr<<"\t"<<&i<<endl;

    when the standard says that the above operation result is undefined then you could say it is also compiler dependent ...
    some compilers might throw up an error others might just give different outputs ( like in my case ).

    Am I right when I make the above statement.

  11. #11
    Programming Sex-God Polymorphic OOP's Avatar
    Join Date
    Nov 2002
    Posts
    1,078
    yup

  12. #12
    Registered User
    Join Date
    Dec 2002
    Posts
    103
    Originally posted by newt
    hmmm......

    Just one more thing then:
    The address stored in the pointer and the address of the
    constant is the same, so how can two values reside in the same
    location
    Well whenever the compiler creates a constant in the non-writable area,
    we have a direct substituion for that constant-reference to value...
    hence does not reach out to the RAM

    Code:
    const int i = 10; // this could be completely optimized
    Having said that if you have created the constant in such a way
    that it can't just stop there.. but has to allocate memory, then it
    does allocate the same too. The pointers that point to this const,
    get that address


    Code:
    const int i = 10;
    int *p = const_cast<int *>(&i); 
    // since u r taking the address of i, 
    //it has no choice but to allocate memory
    *p = 30; // will change the value at the memory allocated for i, 
    cout << i; // gives u 10
    // but still everywhere u use i, it would be an assembly level 
    //direct substitution and hence it does not go to the location to 
    //fecth the value
    Last edited by shiv_tech_quest; 01-21-2003 at 04:56 AM.
    Have a wonderful day.... and keep smiling... you look terrific that way
    signing off...
    shiv... as i know him

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  2. HUGE fps jump
    By DavidP in forum Game Programming
    Replies: 23
    Last Post: 07-01-2004, 10:36 AM
  3. problem with const int inside class (c2258)
    By talz13 in forum C++ Programming
    Replies: 1
    Last Post: 11-23-2003, 06:34 PM
  4. Another overloading "<<" problem
    By alphaoide in forum C++ Programming
    Replies: 18
    Last Post: 09-30-2003, 10:32 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21