Casting
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_castConst 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.(this) )->id = 5; }
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)