Why does const_cast remove constness for a pointer but not for a pointer to a const?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
12
down vote

favorite
3












I understand that const_cast works with pointers and references.



I'm assuming that the input to const_cast should be a pointer or reference. I want to know why it doesn't remove the constness if the input is a pointer/reference to a const int?



The following code works as expected.




  1. const_cast with multilevel pointers



    int main()

    using std::cout;
    #define endl 'n'
    const int * ip = new int(123);
    const int * ptr = ip;
    *const_cast<int*>(ptr) = 321;
    cout << "*ip: " << *ip << endl; // value of *ip is changed to 321



    But when I try a pointer to const int or reference to const int, the value doesn't seem to change.




  2. const_cast with reference to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int & ri = i;
    const_cast<int&>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123




  3. const_cast with pointer to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int * ri = &i;
    *const_cast<int*>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123



(1) works as expected, but I'm unable to comprehend why (2) & (3) don't work the way I think though the input to the const_cast is a pointer/reference.



Please help me understand the philosophy behind this. Thanks.










share|improve this question



















  • 2




    All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
    – Kaldrr
    Aug 31 at 8:08







  • 3




    Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
    – n.m.
    Aug 31 at 8:09






  • 4




    @Kaldrr Example 1 is well defined.
    – n.m.
    Aug 31 at 8:10







  • 10




    Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
    – lubgr
    Aug 31 at 8:10






  • 3




    @lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
    – DevSolar
    Aug 31 at 8:38














up vote
12
down vote

favorite
3












I understand that const_cast works with pointers and references.



I'm assuming that the input to const_cast should be a pointer or reference. I want to know why it doesn't remove the constness if the input is a pointer/reference to a const int?



The following code works as expected.




  1. const_cast with multilevel pointers



    int main()

    using std::cout;
    #define endl 'n'
    const int * ip = new int(123);
    const int * ptr = ip;
    *const_cast<int*>(ptr) = 321;
    cout << "*ip: " << *ip << endl; // value of *ip is changed to 321



    But when I try a pointer to const int or reference to const int, the value doesn't seem to change.




  2. const_cast with reference to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int & ri = i;
    const_cast<int&>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123




  3. const_cast with pointer to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int * ri = &i;
    *const_cast<int*>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123



(1) works as expected, but I'm unable to comprehend why (2) & (3) don't work the way I think though the input to the const_cast is a pointer/reference.



Please help me understand the philosophy behind this. Thanks.










share|improve this question



















  • 2




    All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
    – Kaldrr
    Aug 31 at 8:08







  • 3




    Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
    – n.m.
    Aug 31 at 8:09






  • 4




    @Kaldrr Example 1 is well defined.
    – n.m.
    Aug 31 at 8:10







  • 10




    Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
    – lubgr
    Aug 31 at 8:10






  • 3




    @lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
    – DevSolar
    Aug 31 at 8:38












up vote
12
down vote

favorite
3









up vote
12
down vote

favorite
3






3





I understand that const_cast works with pointers and references.



I'm assuming that the input to const_cast should be a pointer or reference. I want to know why it doesn't remove the constness if the input is a pointer/reference to a const int?



The following code works as expected.




  1. const_cast with multilevel pointers



    int main()

    using std::cout;
    #define endl 'n'
    const int * ip = new int(123);
    const int * ptr = ip;
    *const_cast<int*>(ptr) = 321;
    cout << "*ip: " << *ip << endl; // value of *ip is changed to 321



    But when I try a pointer to const int or reference to const int, the value doesn't seem to change.




  2. const_cast with reference to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int & ri = i;
    const_cast<int&>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123




  3. const_cast with pointer to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int * ri = &i;
    *const_cast<int*>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123



(1) works as expected, but I'm unable to comprehend why (2) & (3) don't work the way I think though the input to the const_cast is a pointer/reference.



Please help me understand the philosophy behind this. Thanks.










share|improve this question















I understand that const_cast works with pointers and references.



I'm assuming that the input to const_cast should be a pointer or reference. I want to know why it doesn't remove the constness if the input is a pointer/reference to a const int?



The following code works as expected.




  1. const_cast with multilevel pointers



    int main()

    using std::cout;
    #define endl 'n'
    const int * ip = new int(123);
    const int * ptr = ip;
    *const_cast<int*>(ptr) = 321;
    cout << "*ip: " << *ip << endl; // value of *ip is changed to 321



    But when I try a pointer to const int or reference to const int, the value doesn't seem to change.




  2. const_cast with reference to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int & ri = i;
    const_cast<int&>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123




  3. const_cast with pointer to const int



    int main()

    using std::cout;
    #define endl 'n'
    const int i = 123;
    const int * ri = &i;
    *const_cast<int*>(ri) = 321;
    cout << "i: " << i << endl; // value in 'i' is 123



(1) works as expected, but I'm unable to comprehend why (2) & (3) don't work the way I think though the input to the const_cast is a pointer/reference.



Please help me understand the philosophy behind this. Thanks.







c++ const-cast






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 31 at 12:39









Boann

35.7k1185116




35.7k1185116










asked Aug 31 at 8:01









Rahul

4662720




4662720







  • 2




    All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
    – Kaldrr
    Aug 31 at 8:08







  • 3




    Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
    – n.m.
    Aug 31 at 8:09






  • 4




    @Kaldrr Example 1 is well defined.
    – n.m.
    Aug 31 at 8:10







  • 10




    Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
    – lubgr
    Aug 31 at 8:10






  • 3




    @lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
    – DevSolar
    Aug 31 at 8:38












  • 2




    All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
    – Kaldrr
    Aug 31 at 8:08







  • 3




    Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
    – n.m.
    Aug 31 at 8:09






  • 4




    @Kaldrr Example 1 is well defined.
    – n.m.
    Aug 31 at 8:10







  • 10




    Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
    – lubgr
    Aug 31 at 8:10






  • 3




    @lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
    – DevSolar
    Aug 31 at 8:38







2




2




All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
– Kaldrr
Aug 31 at 8:08





All 3 examples are undefined behavior, from CppCoreGuidelines: Don't cast away const. It makes a lie out of const. If the variable is actually declared const, the result of "casting away const" is undefined behavior.
– Kaldrr
Aug 31 at 8:08





3




3




Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
– n.m.
Aug 31 at 8:09




Trying to change the value of a const object (const int) is undefined behaviour, this is the reason why 2 and 3 don't work. 1 doesn't have any const int, only an int and const int* that points to it, so it's ok.
– n.m.
Aug 31 at 8:09




4




4




@Kaldrr Example 1 is well defined.
– n.m.
Aug 31 at 8:10





@Kaldrr Example 1 is well defined.
– n.m.
Aug 31 at 8:10





10




10




Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
– lubgr
Aug 31 at 8:10




Do you have some objections against the "n" literal? This endl macro in your snippets make me feel so uncomfortable :)
– lubgr
Aug 31 at 8:10




3




3




@lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
– DevSolar
Aug 31 at 8:38




@lubgr: Forget it, I did not see the #define endl 'n' in there -- that is strange...
– DevSolar
Aug 31 at 8:38












3 Answers
3






active

oldest

votes

















up vote
18
down vote



accepted










There are two kinds of constness.



Constness of an object is an inherent property of an object. It cannot be changed.



Think of a page in a printed book. It can be viewed as a string of characters, and it cannot be changed. It says what it says and that's it. So it's a const string.



Now think of a blackboard. It may have something written on it. You can wipe that and write something else. So the blackboard is a non-const string.



The other kind of constness is pointer and reference constness. This constness is not an inherent property of the pointed-to object, but a permission. It says you are not allowed to modify the object through this pointer. It says nothing about whether the object itself can be modified.



So if you have a const pointer, you don't necessarily know what it really points to. Maybe it's a book page. Maybe it's a blackboard. The pointer doesn't tell.



Now if you do know somehow that it is indeed a blackboard, you can be nasty and demand permission to go ahead and change what's written on it. That's what const_cast does. It gives you permission to do something.



What happens if you demand permission to modify a string, and it turns out to be a printed page? You get your permission, you go ahead and wipe it... and... What exactly happens is undefined. Perhaps nothing at all. Perhaps the print is smeared and you can neither recognise the original string nor write anything on top. Perhaps your world explodes to little pieces. You can try and see, but there's no guarantee the same thing will happen tomorrow.






share|improve this answer






















  • Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
    – Yakk - Adam Nevraumont
    Aug 31 at 15:52











  • @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
    – Martin B.
    Sep 1 at 7:23











  • @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
    – Yakk - Adam Nevraumont
    Sep 1 at 12:29

















up vote
14
down vote













(2) and (3) has the same principle, so I'll talk about (2) only.



The line



const_cast<int&>(ri) = 321;


has undefined behavior.



You cannot modify a const object according to the standard, not even with const_cast. If you remove const from a pointer/reference, and modify the pointed/referenced object, the pointed/referenced object must not been declared as const in the first place.



const_cast should be used only, when you have a const pointer to something for some reason, and you know that something is not declared as const.






share|improve this answer
















  • 2




    Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
    – StoryTeller
    Aug 31 at 9:24


















up vote
3
down vote













Modifying the constant via the const_cast is undefined behaviour.



The compiler sees that you are trying to print a constant variable, knows it can never change so compiles:



cout << "i: " << i << endl;


to:



cout << "i: " << 123 << endl;


see: https://godbolt.org/z/bYb0mx. With optimisations enabled it optimises your code to just printing 123: https://godbolt.org/z/4Ttlmj.



Ultimately compilers make assumptions in order to create faster/smaller code, if you enter the realms of undefined behaviour some of those assumptions may be incorrect and produce surprising results.






share|improve this answer






















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52111035%2fwhy-does-const-cast-remove-constness-for-a-pointer-but-not-for-a-pointer-to-a-co%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    18
    down vote



    accepted










    There are two kinds of constness.



    Constness of an object is an inherent property of an object. It cannot be changed.



    Think of a page in a printed book. It can be viewed as a string of characters, and it cannot be changed. It says what it says and that's it. So it's a const string.



    Now think of a blackboard. It may have something written on it. You can wipe that and write something else. So the blackboard is a non-const string.



    The other kind of constness is pointer and reference constness. This constness is not an inherent property of the pointed-to object, but a permission. It says you are not allowed to modify the object through this pointer. It says nothing about whether the object itself can be modified.



    So if you have a const pointer, you don't necessarily know what it really points to. Maybe it's a book page. Maybe it's a blackboard. The pointer doesn't tell.



    Now if you do know somehow that it is indeed a blackboard, you can be nasty and demand permission to go ahead and change what's written on it. That's what const_cast does. It gives you permission to do something.



    What happens if you demand permission to modify a string, and it turns out to be a printed page? You get your permission, you go ahead and wipe it... and... What exactly happens is undefined. Perhaps nothing at all. Perhaps the print is smeared and you can neither recognise the original string nor write anything on top. Perhaps your world explodes to little pieces. You can try and see, but there's no guarantee the same thing will happen tomorrow.






    share|improve this answer






















    • Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
      – Yakk - Adam Nevraumont
      Aug 31 at 15:52











    • @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
      – Martin B.
      Sep 1 at 7:23











    • @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
      – Yakk - Adam Nevraumont
      Sep 1 at 12:29














    up vote
    18
    down vote



    accepted










    There are two kinds of constness.



    Constness of an object is an inherent property of an object. It cannot be changed.



    Think of a page in a printed book. It can be viewed as a string of characters, and it cannot be changed. It says what it says and that's it. So it's a const string.



    Now think of a blackboard. It may have something written on it. You can wipe that and write something else. So the blackboard is a non-const string.



    The other kind of constness is pointer and reference constness. This constness is not an inherent property of the pointed-to object, but a permission. It says you are not allowed to modify the object through this pointer. It says nothing about whether the object itself can be modified.



    So if you have a const pointer, you don't necessarily know what it really points to. Maybe it's a book page. Maybe it's a blackboard. The pointer doesn't tell.



    Now if you do know somehow that it is indeed a blackboard, you can be nasty and demand permission to go ahead and change what's written on it. That's what const_cast does. It gives you permission to do something.



    What happens if you demand permission to modify a string, and it turns out to be a printed page? You get your permission, you go ahead and wipe it... and... What exactly happens is undefined. Perhaps nothing at all. Perhaps the print is smeared and you can neither recognise the original string nor write anything on top. Perhaps your world explodes to little pieces. You can try and see, but there's no guarantee the same thing will happen tomorrow.






    share|improve this answer






















    • Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
      – Yakk - Adam Nevraumont
      Aug 31 at 15:52











    • @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
      – Martin B.
      Sep 1 at 7:23











    • @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
      – Yakk - Adam Nevraumont
      Sep 1 at 12:29












    up vote
    18
    down vote



    accepted







    up vote
    18
    down vote



    accepted






    There are two kinds of constness.



    Constness of an object is an inherent property of an object. It cannot be changed.



    Think of a page in a printed book. It can be viewed as a string of characters, and it cannot be changed. It says what it says and that's it. So it's a const string.



    Now think of a blackboard. It may have something written on it. You can wipe that and write something else. So the blackboard is a non-const string.



    The other kind of constness is pointer and reference constness. This constness is not an inherent property of the pointed-to object, but a permission. It says you are not allowed to modify the object through this pointer. It says nothing about whether the object itself can be modified.



    So if you have a const pointer, you don't necessarily know what it really points to. Maybe it's a book page. Maybe it's a blackboard. The pointer doesn't tell.



    Now if you do know somehow that it is indeed a blackboard, you can be nasty and demand permission to go ahead and change what's written on it. That's what const_cast does. It gives you permission to do something.



    What happens if you demand permission to modify a string, and it turns out to be a printed page? You get your permission, you go ahead and wipe it... and... What exactly happens is undefined. Perhaps nothing at all. Perhaps the print is smeared and you can neither recognise the original string nor write anything on top. Perhaps your world explodes to little pieces. You can try and see, but there's no guarantee the same thing will happen tomorrow.






    share|improve this answer














    There are two kinds of constness.



    Constness of an object is an inherent property of an object. It cannot be changed.



    Think of a page in a printed book. It can be viewed as a string of characters, and it cannot be changed. It says what it says and that's it. So it's a const string.



    Now think of a blackboard. It may have something written on it. You can wipe that and write something else. So the blackboard is a non-const string.



    The other kind of constness is pointer and reference constness. This constness is not an inherent property of the pointed-to object, but a permission. It says you are not allowed to modify the object through this pointer. It says nothing about whether the object itself can be modified.



    So if you have a const pointer, you don't necessarily know what it really points to. Maybe it's a book page. Maybe it's a blackboard. The pointer doesn't tell.



    Now if you do know somehow that it is indeed a blackboard, you can be nasty and demand permission to go ahead and change what's written on it. That's what const_cast does. It gives you permission to do something.



    What happens if you demand permission to modify a string, and it turns out to be a printed page? You get your permission, you go ahead and wipe it... and... What exactly happens is undefined. Perhaps nothing at all. Perhaps the print is smeared and you can neither recognise the original string nor write anything on top. Perhaps your world explodes to little pieces. You can try and see, but there's no guarantee the same thing will happen tomorrow.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 31 at 8:48

























    answered Aug 31 at 8:40









    n.m.

    68.7k882165




    68.7k882165











    • Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
      – Yakk - Adam Nevraumont
      Aug 31 at 15:52











    • @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
      – Martin B.
      Sep 1 at 7:23











    • @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
      – Yakk - Adam Nevraumont
      Sep 1 at 12:29
















    • Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
      – Yakk - Adam Nevraumont
      Aug 31 at 15:52











    • @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
      – Martin B.
      Sep 1 at 7:23











    • @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
      – Yakk - Adam Nevraumont
      Sep 1 at 12:29















    Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
    – Yakk - Adam Nevraumont
    Aug 31 at 15:52





    Good answer; but you might want to mention what actually happens here. The optimizer sees const int i = 123; and says "i must always be 123". This is correct, because there is no way except UB to change it. Then when you use i elsewhere, it says "why use i when I can use 123? That sounds faster!" Meanwhile, i has a memory location, and that memory location was modified; in a case where you have a pointer to i that the compiler cannot prove points to i, it gets 321 as it actually reads the memory.
    – Yakk - Adam Nevraumont
    Aug 31 at 15:52













    @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
    – Martin B.
    Sep 1 at 7:23





    @Yakk "Meanwhile, i has a memory location, and that memory location was modified;" - No. Not necessarily. Since i is int const it could be located in ROM and every write access to it is dropped by the compiler because of UB...
    – Martin B.
    Sep 1 at 7:23













    @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
    – Yakk - Adam Nevraumont
    Sep 1 at 12:29




    @martin yes, it is UB. I was describing a common scenario, not a guaranteed one. (As an aside, outside of main, placing address-taken automatic storage variables in ROM can be difficult; if there is any possibility of recursion eaxh recursion needs distinct addresses.)
    – Yakk - Adam Nevraumont
    Sep 1 at 12:29












    up vote
    14
    down vote













    (2) and (3) has the same principle, so I'll talk about (2) only.



    The line



    const_cast<int&>(ri) = 321;


    has undefined behavior.



    You cannot modify a const object according to the standard, not even with const_cast. If you remove const from a pointer/reference, and modify the pointed/referenced object, the pointed/referenced object must not been declared as const in the first place.



    const_cast should be used only, when you have a const pointer to something for some reason, and you know that something is not declared as const.






    share|improve this answer
















    • 2




      Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
      – StoryTeller
      Aug 31 at 9:24















    up vote
    14
    down vote













    (2) and (3) has the same principle, so I'll talk about (2) only.



    The line



    const_cast<int&>(ri) = 321;


    has undefined behavior.



    You cannot modify a const object according to the standard, not even with const_cast. If you remove const from a pointer/reference, and modify the pointed/referenced object, the pointed/referenced object must not been declared as const in the first place.



    const_cast should be used only, when you have a const pointer to something for some reason, and you know that something is not declared as const.






    share|improve this answer
















    • 2




      Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
      – StoryTeller
      Aug 31 at 9:24













    up vote
    14
    down vote










    up vote
    14
    down vote









    (2) and (3) has the same principle, so I'll talk about (2) only.



    The line



    const_cast<int&>(ri) = 321;


    has undefined behavior.



    You cannot modify a const object according to the standard, not even with const_cast. If you remove const from a pointer/reference, and modify the pointed/referenced object, the pointed/referenced object must not been declared as const in the first place.



    const_cast should be used only, when you have a const pointer to something for some reason, and you know that something is not declared as const.






    share|improve this answer












    (2) and (3) has the same principle, so I'll talk about (2) only.



    The line



    const_cast<int&>(ri) = 321;


    has undefined behavior.



    You cannot modify a const object according to the standard, not even with const_cast. If you remove const from a pointer/reference, and modify the pointed/referenced object, the pointed/referenced object must not been declared as const in the first place.



    const_cast should be used only, when you have a const pointer to something for some reason, and you know that something is not declared as const.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Aug 31 at 8:13









    geza

    9,88822465




    9,88822465







    • 2




      Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
      – StoryTeller
      Aug 31 at 9:24













    • 2




      Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
      – StoryTeller
      Aug 31 at 9:24








    2




    2




    Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
    – StoryTeller
    Aug 31 at 9:24





    Another use case is to interoperate with API's (often early C) that don't modify the object, yet aren't const correct.
    – StoryTeller
    Aug 31 at 9:24











    up vote
    3
    down vote













    Modifying the constant via the const_cast is undefined behaviour.



    The compiler sees that you are trying to print a constant variable, knows it can never change so compiles:



    cout << "i: " << i << endl;


    to:



    cout << "i: " << 123 << endl;


    see: https://godbolt.org/z/bYb0mx. With optimisations enabled it optimises your code to just printing 123: https://godbolt.org/z/4Ttlmj.



    Ultimately compilers make assumptions in order to create faster/smaller code, if you enter the realms of undefined behaviour some of those assumptions may be incorrect and produce surprising results.






    share|improve this answer


























      up vote
      3
      down vote













      Modifying the constant via the const_cast is undefined behaviour.



      The compiler sees that you are trying to print a constant variable, knows it can never change so compiles:



      cout << "i: " << i << endl;


      to:



      cout << "i: " << 123 << endl;


      see: https://godbolt.org/z/bYb0mx. With optimisations enabled it optimises your code to just printing 123: https://godbolt.org/z/4Ttlmj.



      Ultimately compilers make assumptions in order to create faster/smaller code, if you enter the realms of undefined behaviour some of those assumptions may be incorrect and produce surprising results.






      share|improve this answer
























        up vote
        3
        down vote










        up vote
        3
        down vote









        Modifying the constant via the const_cast is undefined behaviour.



        The compiler sees that you are trying to print a constant variable, knows it can never change so compiles:



        cout << "i: " << i << endl;


        to:



        cout << "i: " << 123 << endl;


        see: https://godbolt.org/z/bYb0mx. With optimisations enabled it optimises your code to just printing 123: https://godbolt.org/z/4Ttlmj.



        Ultimately compilers make assumptions in order to create faster/smaller code, if you enter the realms of undefined behaviour some of those assumptions may be incorrect and produce surprising results.






        share|improve this answer














        Modifying the constant via the const_cast is undefined behaviour.



        The compiler sees that you are trying to print a constant variable, knows it can never change so compiles:



        cout << "i: " << i << endl;


        to:



        cout << "i: " << 123 << endl;


        see: https://godbolt.org/z/bYb0mx. With optimisations enabled it optimises your code to just printing 123: https://godbolt.org/z/4Ttlmj.



        Ultimately compilers make assumptions in order to create faster/smaller code, if you enter the realms of undefined behaviour some of those assumptions may be incorrect and produce surprising results.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Aug 31 at 8:53

























        answered Aug 31 at 8:20









        Alan Birtles

        5,617531




        5,617531



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52111035%2fwhy-does-const-cast-remove-constness-for-a-pointer-but-not-for-a-pointer-to-a-co%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay