Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess Casting STL Modern C++ Misc Books ----

Casting


Contents

Const Cast

We can use the const cast to remove the constness of something. However we should not use it to remove the constness of the original variable if it was declared as a constant.

File: const1.cpp
#include <iostream>

using namespace std ;

int main()
{
    int x1 = 10;
    const int* ptr1 = &x1 ;

    //Can't do because ptr points to a constant
    //*ptr1 = 20 ;

    int* ptr2 = const_cast<int*>(  ptr1 ); // Casting away constness
    *ptr2 = 20 ;
    cout << "x1:" << x1 << endl ;


    const int x3 = 10;
    int* ptr3 = const_cast<int*>( &x3 ) ;
    *ptr3 = 22 ;
    //Doesn't change the original x3 . Undefined
    //behavior. Not recommended
    cout << "x3:" << x3 << endl ;



    int x4 = 10;
    const int& constRef = x4 ;

    // Attempting to modify value through constRef directly will result in a compiler error
    // constRef = 20; // Error: assignment of read-only reference

    // Use const_cast to remove constness from the reference
    int& nonConstRef = const_cast<int&>(constRef);
    nonConstRef = 20;

    cout << "x4: " << x4 << endl;
    // Output: Value: 20






    return 0;
}

Output:
$ rm a.exe ; g++ const1.cpp ; ./a.exe
x1:20
x3:10
x4: 20

We have:
    int x1 = 10;
    const int* ptr1 = &x1 ;

We have a pointer to a constant "ptr1" that has
been assigned the address of "x1" . So we cannot change
it's value.

    //Can't do because ptr points to a constant
    //*ptr1 = 20 ;

However we can remove the constness of the pointer by using
the const cast. We can do it because the original variable
is not a constant.

    int* ptr2 = const_cast(  ptr1 ); // Casting away constness
    *ptr2 = 20 ;
    cout << "x1:" << x1 << endl ;

Now in the next section in the code we have:

    const int x3 = 10;
    int* ptr3 = const_cast( &x3 ) ;
    *ptr3 = 22 ;
    //Doesn't change the original x3 . Undefined
    //behavior. Not recommended
    cout << "x3:" << x3 << endl ;

This leads to undefined behavior and doesn't actually change
the value of the x3. We can also remove the constness of a
constant reference.


    int x4 = 10;
    const int& constRef = x4 ;
    // Attempting to modify value through constRef directly will result in a compiler error
    // constRef = 20; // Error: assignment of read-only reference
    // Use const_cast to remove constness from the reference
    int& nonConstRef = const_cast(constRef);
    nonConstRef = 20;
    cout << "x4: " << x4 << endl;
    // Output: Value: 20



File: const2.cpp
#include <iostream>
using namespace std ;



int main()
{
     int x1 = 10;
     float f1 = 10.5 ;

     //compiler error
     int x2 = const_cast<int>(x1);

     char x3 = const_cast<char>(x1);



}
$ rm a.exe ; g++ const2.cpp ; ./a.exe
const2.cpp: In function ‘int main()’:
const2.cpp:12:15: error: invalid use of ‘const_cast’ with
type ‘int’, which is not a pointer, reference, nor
a pointer-to-data-member type
   12 |      int x2 = const_cast(x1);
      |               ^~~~~~~~~~~~~~~~~~~
const2.cpp:14:16: error: invalid use of ‘const_cast’ with
type ‘char’, which is not a pointer, reference, nor
a pointer-to-data-member type
   14 |      char x3 = const_cast(x1);
      |                ^~~~~~~~~~~~~~~~~~~~
bash: ./a.exe: No such file or directory

We cannot use const casting with normal types. The system
expects the type to be a pointer or a reference. That makes
sense as we do not want to remove the constness of an
existing variable.


File: const3.cpp
#include <iostream>
using namespace std ;

#include <iostream>
using namespace std;

class student
{
private:
    int id ;
public:
    // constructor
    student(int idP) : id(idP) {}

    // A const function. Cannot change the data
    // members of the class.
    //changes roll with the help of const_cast
    void function1() const
    {
        ( const_cast <student*> (this) )->id = 5;
    }

    int getId() { return id; }
};

int main(void)
{
    student s1(3);
    cout << "Old id number: " << s1.getId() << endl;

    s1.function1();

    cout << "New id number: " << s1.getId() << endl;

    return 0;
}




$ rm a.exe ; g++ const3.cpp ; ./a.exe
Old id number: 3
New id number: 5

The above program shows another use case of the const cast.
We have a method in a class that is defined as const. That
means the method cannot modify the class data variables unless
that variable is defined as mutable.

However we can remove that restriction by using const cast as
shown in the function:

	void function1() const
	{
		( const_cast  (this) )->id = 5;
	}


Const cast should be used in very limited circumstances. One such scenario may be old "C" code that has a function taking a non const parameter.

File: const4.cpp
#include <iostream>
#include <cstring> // For strlen and strcpy

// An example of an "old C function" that expects a char* for modification
// even if it might not always modify it.

 void process_string(char* str)
 {
        if (str != nullptr) {
            std::cout << "Processing string: " << str << std::endl;
            // Simulate a modification if needed
            if (strlen(str) > 0) {
                str[0] = toupper(str[0]); // Modify the first character
            }
        }
}


int main() {
    // Case 1: Modifying a non-const string through a const pointer
    char buffer[50] = "hello world";
    const char* const_buffer_ptr = buffer; // A const pointer to non-const data

    // We need to const_cast to pass it to process_string
    // because process_string expects a non-const char*
    process_string(const_cast<char*>(const_buffer_ptr));
    std::cout << "After processing (Case 1): " << buffer << std::endl;

    // Case 2: Attempting to modify a truly const string (Undefined Behavior)
    const char* truly_const_string = "immutable"; // This data is in read-only memory
    process_string(const_cast<char*>(truly_const_string));
    std::cout << "After processing (Case 2): " << truly_const_string << std::endl;

    // Using const_cast here to call process_string, but modifying *truly_const_string
    // results in undefined behavior because the underlying object is truly const.
    // This is generally discouraged and can lead to crashes or unexpected results.
    // For demonstration purposes only:
    // process_string(const_cast<char*>(truly_const_string));
    // std::cout << "After processing (Case 2 - UB): " << truly_const_string << std::endl;

    return 0;
}

$ g++ const4.cpp ; ./a.exe
Processing string: hello world
After processing (Case 1): Hello world
Processing string: immutable
Segmentation fault (core dumped)